/**
 * Dealer-FX Component Overrides
 * -----------------------------------------------------------------------------
 * Component-level styling on top of the parent theme. Add one clearly-labeled section
 * per component. All values reference brand tokens.
 *
 * Depends on: brand-tokens.css
 */

/* --- Hero video background: stop the overlay snapping in ------------------- */
/* The parent theme reveals the row background on a `.loaded` class (added when
   the video is ready), but the gradient overlay has a 0s transition, so with no
   poster the bright first frame shows and the dark gradient pops in on load.
   Keep the hero overlay painted from the first frame and ease any change.
   NOTE: `#fws_6a72cf4d82323` is the parent theme's generated row id — if the
   hero row is rebuilt and the id changes, add a stable "Extra class name" on the
   row (e.g. dfx-hero) and retarget this rule. Scoped; parent theme untouched. */
#fws_6a72cf4d82323 .row-bg-overlay {
	opacity: 1 !important;
	/* Promote the overlay to its own compositing layer so it paints above the
	   video's GPU layer from first frame (without this it only composites above
	   after a scroll/repaint). */
	transform: translateZ(0);
	will-change: transform;
	transition: opacity 0.5s ease !important;
}
#fws_6a72cf4d82323 .row-bg-wrap .row-bg {
	transition: opacity 0.5s ease !important;
}

/* --- Header: spacing between logo and main nav ----------------------------- */
/* Push the main menu (not the utility "buttons" group) right of the logo. */
#header-outer #top nav > ul.sf-menu:not(.buttons) {
	margin-left: var(--dfx-nav-logo-gap);
}

/* --- Main navigation: top-level (first layer) links ------------------------- */
/* Selectors mirror the parent theme's own nav specificity so the override lands
   without needing !important. */
#header-outer #top nav > ul.sf-menu > li > a,
#header-outer #top nav > ul.sf-menu > li > a .menu-title-text {
	color: var(--dfx-nav-link);
}

#header-outer #top nav > ul.sf-menu > li > a:hover,
#header-outer #top nav > ul.sf-menu > li > a:hover .menu-title-text,
#header-outer #top nav > ul.sf-menu > li > a:focus,
#header-outer #top nav > ul.sf-menu > li > a:focus .menu-title-text,
#header-outer #top nav > ul.sf-menu > li.sfHover > a,
#header-outer #top nav > ul.sf-menu > li.sfHover > a .menu-title-text {
	color: var(--dfx-nav-link-hover);
}

/* --- The nav type scale — THE CHILD THEME OWNS SIZE, NOT FAMILY ---------------
   Every text size in the header came from Salient's Theme Options and none of it was
   on the ramp: top-level links and megamenu items at 14.4px, megamenu column heads at
   11.2px, and megamenu sub-items on a 1.71 leading that read as a list of unrelated
   lines rather than a set.

   WHY THIS IS THE CHILD THEME'S TO TAKE, given the panel had it. Salient emits
   family, size, leading and weight as ONE bundle, gated on the FAMILY field —
   css/fonts.php:412 checks `navigation_font_family['attrs_in_use']` and then writes
   all four properties. So the 14.4px was never a decision anybody made in that
   panel; it rode along on the choice to set the site font to Inter. Nothing in Theme
   Options says the nav should be 14.4px.

   SO THE SPLIT IS BY PROPERTY, NOT BY REGION: the child theme owns size, leading and
   tracking, and Theme Options keeps font-family and color, which are the things
   actually chosen there. That also means this block does NOT need the fields cleared
   in the panel, which matters — option state lives in the DB, dies in a Kinsta
   rebuild and already differs between local and staging.

   THESE RULES TARGET THE SPAN, NOT THE ANCHOR, and that is deliberate rather than
   incidental. Salient sets font-size on the `a`; the text lives in
   `span.menu-title-text`, so a size on the span wins for the text without competing
   with the parent theme's anchor rule at all. Color above already uses both, because
   color has to cover the anchor for the cases where no span is emitted.

   ONE SIZE FOR THE WHOLE MEGAMENU, differentiated by case and weight rather than by
   size — 14px throughout, column heads uppercase at 600, the featured item 600, the
   rest 500. Four sizes became one. This is the pattern the footer already uses. */
#header-outer #top nav > ul.sf-menu > li > a .menu-title-text,
#header-outer #top nav ul.sub-menu li > a .menu-title-text {
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-ui);
	/* Weight pinned: Theme Options gives 500 locally and 400 on Kinsta, and 400 at 14px
	   in mid-gray reads thin. 500 is the value that looked right. */
	font-weight: 500;
}

/* THE MEGAMENU COLUMN HEADS, AND THEY NOW MATCH THE FOOTER'S EXACTLY.
   `.nectar-inherit-h6` is Salient deriving these from its h6 typography option, which
   is 11.2px/0.13em — the value recorded as under AA and outstanding as "a DB change".
   It is not a DB change any more. This is the theme's chrome-label role, so it reads
   --dfx-size-label like the footer widget titles and the "Trusted by" separator, and
   restates the caps treatment because a span in a menu inherits none of it.

   0.14em NOT 0.13em, closing a gap that existed for no reason: the footer titles and
   these were the same voice at two tracking values because one came from the panel
   and one from this file. 2-3-4 to clear the generic megamenu rule above at 2-2-4 —
   the extra class alone is not enough when the other selector carries more elements. */
#header-outer #top nav ul.sub-menu li > a .menu-title-text.nectar-inherit-h6 {
	font-size: var(--dfx-size-label);
	line-height: 1.4;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	/* WEIGHT IS PINNED HERE BECAUSE THE TWO ENVIRONMENTS DISAGREE ABOUT IT, and that is
	   only visible if you measure staging. dealerfx.test renders these heads at 600 and
	   dealerfx.kinsta.cloud renders them at 400 — same theme, same markup, different h6
	   weight in Theme Options. So the first version of this rule looked complete locally
	   while shipping a 400-weight header label to staging.

	   THAT 400 IS MOST OF WHY THE HEADER READ AS "A DIFFERENT FONT ALTOGETHER" from the
	   footer. It is not a different family — both compute Inter and both measure identical
	   to a canvas-rendered Inter to 0.00px. It is 400 in #9AA0A6 against 600 in #676E7E,
	   and at label size that difference in weight plus a 2:1 difference in contrast reads
	   as a different typeface rather than as the same label twice.

	   Fourth "true on local, wrong on staging" bug in this theme's history and the third
	   in the footer/header region. Measure Kinsta.

	   COLOR IS --dfx-column-head-ink, WHICH IS STEEL GRAY AND A KNOWN AA FAILURE. Chosen
	   deliberately; the arithmetic and the trade are recorded on the token in
	   brand-tokens' companion block in brand-base.css. The point that survives regardless
	   of the value: this is stated here rather than inherited from Salient's h6 color in
	   Theme Options, so the header and the footer now agree by construction and agree on
	   both environments. Changing the two together is one token edit. */
	font-weight: var(--dfx-weight-emphasis);
	/* COLOR IS THE PROPERTY THAT WAS ACTUALLY INCONSISTENT, and it took a screenshot to
	   see it — size, weight, tracking, family and case already matched the footer exactly
	   once this rule existed. Measured: the megamenu heads rendered #9AA0A6 Steel Gray at
	   2.64:1 while the footer titles rendered #676E7E Pewter at 5.11:1. Same words, same
	   role, two inks, and only one of them legal.

	   THE STEEL GRAY CAME FROM SALIENT'S h6 COLOR IN THEME OPTIONS, which is the thing
	   recorded as "the megamenu column heads are still under AA, that half is a DB change,
	   still outstanding". It is not a DB change. --dfx-label-ink is the theme's label ink
	   role, it is what the footer titles already read, and it brings the dark-band
	   re-pointing with it — so this one declaration makes the header match the footer,
	   clears AA at 5.11:1, and removes the last Theme Options dependency in the megamenu.

	   line-height 1.4 NOT --dfx-line-height-ui, matching the footer titles literally. The
	   two were 1.45 and 1.40, which is invisible on a single-line caps label, but "same
	   size, same weight, etc." is easier to keep true if the numbers are the same number. */
	color: var(--dfx-column-head-ink);
}

/* Space below the column heads, matched to the footer's. The footer widget titles carry
   20px under a 13px label; these had only the 6px of padding header-megamenu.css gives
   every megamenu link. Stated as a total rather than added to that 6px so the gap does
   not move if Salient's padding does. */
#header-outer nav > ul > li.megamenu > ul > li > a {
	padding-bottom: 1.25rem;
}

/* The featured megamenu item ("Service Intelligence Platform Overview"). Chrome size, 600 to carry the
   emphasis — stated rather than left to Salient's h5 option, and needed here because the
   rule above now pins 500 and this selector is more specific. */
#header-outer #top nav ul.sub-menu li > a .menu-title-text.nectar-inherit-h5 {
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-ui);
	font-weight: var(--dfx-weight-emphasis);
}

/* --- Utility (secondary) navigation ---------------------------------------- */
/* The "buttons" menu group holds Support, Client login, and the CTA. The caption step,
   one below the main nav's 14px — it was 0.81rem/12.96px, described here as "90% of
   the parent theme's default 14.4px" back when that default was what the nav rendered.
   Both numbers are the theme's own now, and 13 against 14 is the same relationship the
   hand-set values were reaching for. */
#header-outer #top nav > ul.buttons > li > a {
	font-size: var(--dfx-size-caption);
}

/* Tighten spacing between the utility text links (leaves the CTA pill intact). */
#header-outer #top nav > ul.buttons > li.nectar-regular-menu-item > a {
	padding-left: var(--dfx-utility-nav-pad);
	padding-right: var(--dfx-utility-nav-pad);
}

/* --- "Book a demo" CTA: inverted primary button ---------------------------- */
/* Light pill with Obsidian text — the header's primary action on the dark bar.
   the parent theme paints the pill via the anchor's ::before. */
#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a:before {
	background-color: var(--dfx-btn-inverted-fill);
	border: none;
}

#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a:hover:before,
#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a:focus:before {
	background-color: var(--dfx-btn-inverted-fill-hover);
}

/* Pull the pill flush to the container edge. The li already ends at the container
   width; the anchor paints the pill and carries 20px of side margin from the parent
   theme's dynamic styles, so the pill sat 20px inside the content edge. Salient zeroes
   this itself, but only for data-lhe="animated_underline" — ours is "default". */
#header-outer #top nav > ul.buttons > li.button_solid_color_2:last-child > a {
	margin-right: 0;
}

#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a,
#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a .menu-title-text,
#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a:hover,
#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a:focus,
#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a:hover .menu-title-text,
#header-outer #top nav > ul.buttons > li.button_solid_color_2 > a:focus .menu-title-text {
	color: var(--dfx-btn-inverted-text);
}

/* --- "Trusted by" separator (WPBakery Separator-with-text) ------------------ */
/* Match the prototype: small uppercase tracked label + thin, faint lines, instead
   of the parent theme's larger title-case label with prominent lines. Scoped to the
   homepage.

   ONE OF THREE STATED EXCEPTIONS TO brand-base's "no font-size on a heading outside
   the scale block", and it used to claim to be the only one. The other two are the
   page-header title in brand-base.css, which has to mirror Salient's over-specific
   selectors to be reached at all, and the footer widget h4 further down this file.
   All three share the same shape: the element is not ours, so the level it arrives at
   is not a design decision and the size has to be restated. The full list is here
   because "the one exception" is the kind of claim that quietly becomes false, and a
   reader checking the invariant needs to know what they are allowed to find.

   It is an exception rather than a bug because the element is not ours: WPBakery's
   Separator-with-text emits whichever heading level the editor picked in the element
   settings, and the thing it emits is a decorative label, not a rung of the document
   outline. All four levels are listed for that reason — the selector cannot know
   which one the builder wrote. Every one of the three reads a scale token, so the
   invariant that actually matters — no off-scale heading size anywhere — holds even
   where the letter of the rule does not.

   THE SIZE IS --dfx-size-label, NOT --dfx-size-h6, and the difference matters. This
   read the h6 step for a while, which was fine when h6 was 13–14px and wrong the
   moment h6 became 16px: the separator followed it up and started shouting. It was
   never really a heading step — this is CHROME, a decorative rule with a word on it,
   not a rung of the document outline. --dfx-size-label exists for exactly that job
   and is shared with .dfx-eyebrow and the footer widget titles.

   THE UPPERCASE AND TRACKING ARE RESTATED HERE, AND CANNOT BE INHERITED. This rule
   targets h1 through h4, because WPBakery emits whichever level the editor picked in
   the element settings, and none of them is an h6 — so nothing can be picked up from
   the h6 label block. Keep these two values in step with it by hand; that block is
   the source and this is a copy, and the copy exists only because the element is not
   ours to re-tag.

   COLOR IS --dfx-label-ink, which is both the fix to a contrast failure and the
   reason this now works on any surface. It was --dfx-steel-gray #9AA0A6 at 2.64:1,
   under AA, carried deliberately so this matched the megamenu exactly — a decision
   that traded legibility for consistency with something that was itself broken. The
   label ink resolves to Pewter at 4.72:1 on light, and re-points itself on dark bands
   through the escape hatches in brand-base.css, which a flat gray never did. The
   megamenu is now the only one of the pair still failing. */
.home .vc_separator.vc_separator-has-text h1,
.home .vc_separator.vc_separator-has-text h2,
.home .vc_separator.vc_separator-has-text h3,
.home .vc_separator.vc_separator-has-text h4 {
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-label);
	font-weight: var(--dfx-weight-emphasis);
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--dfx-label-ink);
}

.home .vc_separator.vc_separator-has-text .vc_sep_line {
	border-top-width: 1px !important;
	border-top-color: rgba(255, 255, 255, 0.12) !important;
}


/* --- Breadcrumbs ------------------------------------------------------------ */
/* Rendered by template-parts/breadcrumbs.php on the content model post types.
   Salient's own breadcrumb helper is a Yoast wrapper and this site runs
   SmartCrawl, so there is no parent theme component to extend here.

   The separator is a CSS ::before on the pseudo-element rather than a character
   in the markup, so it is never selected when copying the trail and never read
   aloud by a screen reader — the <ol> already conveys the sequence. */
.dfx-breadcrumbs {
	margin-bottom: 1.25rem;
}

.dfx-breadcrumbs__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	/* The parent theme puts list-style and padding on most ul/ol. */
	margin: 0;
	padding: 0;
	list-style: none;
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-caption); /* 13px */
	line-height: var(--dfx-line-height-ui);
	color: var(--dfx-color-text-muted);
}

.dfx-breadcrumbs__item {
	display: flex;
	align-items: center;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dfx-breadcrumbs__item + .dfx-breadcrumbs__item::before {
	content: "\203A"; /* Single right angle quote. */
	margin: 0 0.5rem;
	color: var(--dfx-steel-gray);
}

.dfx-breadcrumbs__item a {
	color: var(--dfx-color-text-muted);
	text-decoration: none;
	border-bottom: 1px solid transparent;
}

.dfx-breadcrumbs__item a:hover,
.dfx-breadcrumbs__item a:focus {
	color: var(--dfx-color-link-hover);
	border-bottom-color: currentColor;
}

/* The current page. Not a link, and weighted so the end of the trail reads as
   "you are here" without needing a color to say it. */
.dfx-breadcrumbs__item [aria-current="page"] {
	font-weight: var(--dfx-weight-emphasis);
	color: var(--dfx-color-text);
}

/* --- Product header band ---------------------------------------------------- */
/* THE DEFAULT PRODUCT HEADER. Rendered by single-dfx_product.php above
   .container-wrap, so it is genuinely full-bleed rather than fighting Salient's
   gutter with negative margins. It stands down when the page has a Product Hero
   element, which brings its own full_width_section row.

   Both headers render the SAME template part — template-parts/product/hero.php,
   from Hero::args() — so everything inside is styled by the .dfx-hero rules
   further down this file. What follows only paints the band around it. The one
   deliberate exception is the breadcrumb, which needs a light-on-dark treatment
   here that it does not need anywhere else.

   COLOR COMES FROM THE PAGE, NOT FROM HERE. single-dfx_product.php sets
   --dfx-band-bg, --dfx-band-heading and optionally --dfx-band-subhead as inline
   custom properties, resolved by Band_Theme::resolve() — the product's own
   override, else its product_category term, else that term's ancestors, else
   Obsidian on Signal White. The fallbacks below are the same brand default, so the
   band still renders correctly if the attribute is ever missing rather than
   collapsing to white-on-white.

   Custom properties rather than inline `background` and `color` so this file keeps
   deciding which properties consume them — the subhead derives 74% of the text
   color, and that arithmetic belongs in CSS. */
.dfx-product-band {
	background-color: var(--dfx-band-bg, var(--dfx-obsidian));
	color: var(--dfx-band-heading, var(--dfx-signal-white));
}

/* Clearance for the transparent navigation. Products always start transparent
   (see inc/salient-page-header.php), so the nav sits over this band and its
   content has to start below it.

   Salient's #header-space is 72px at desktop and the nav shrinks on scroll, so
   the padding is generous rather than exact — matching the nav height precisely
   would leave the headline touching the logo. The hero variant does not get this
   rule: its clearance is the builder row's own top padding, and adding ours on
   top would double it.

   Width and horizontal gutter are NOT set here. The element also carries
   Salient's .container class, so the band's copy aligns with the content below it
   and follows the container width theme option instead of a number of ours that
   would drift from it. Only the vertical padding is ours. */
.dfx-product-band__inner {
	padding-top: 7.5rem;
	padding-bottom: 5rem;
}

@media (max-width: 999px) {
	.dfx-product-band__inner {
		padding-top: 6rem;
		padding-bottom: 3.5rem;
	}
}

/* --- The lifted hero row's measure ------------------------------------------ */
/* THE OTHER HEADER'S CONTAINER. single-dfx_product.php lifts the Product Hero
   element's row above the in-page menu and wraps it in Salient's .container,
   because full_width_section.php only emits an inner container under
   fullpage.js — a full-width-BACKGROUND row takes its content width from
   .container.main-content, which the lift moves it out of.

   `width: 100%` IS LOAD-BEARING. #ajax-content-wrap is a column flex container,
   and .container carries `margin: 0 auto`; auto margins consume the free space
   and cancel the stretch, so the box shrank to its content — 860px where the
   submenu bar's container measured 1100px, and the copy stopped lining up with
   it. This resolves against the flex container and max-width still caps it.

   `align-self: stretch` looks like the flexbox-native answer and does nothing
   here, for the same reason: auto margins outrank it. */
.dfx-product-header {
	width: 100%;
}

/* Breadcrumbs on dark. The default rules are tuned for a light page, so the
   contrast inverts here rather than being restated: white at 70% for the trail,
   full white for the current page, which keeps the "you are here" signal without
   relying on color alone. */
/* Breadcrumb to eyebrow. Generous, because these are two different kinds of thing
   — one is navigation out of the page, the other is the start of its content — and
   at 2rem they read as a single stacked block. */
.dfx-product-band .dfx-breadcrumbs {
	margin-bottom: 5rem;
}

@media (max-width: 999px) {
	.dfx-product-band .dfx-breadcrumbs {
		margin-bottom: 3.5rem;
	}
}

/* Derived from the band's own text color rather than hardcoded white, because the
   band is themeable — a light surface with an Obsidian label would otherwise have
   rendered white breadcrumbs onto near-white.

   MIXED AGAINST THE VARIABLE, NOT AGAINST currentColor, and the list and item are
   both named. The default breadcrumb rules set Slate Graphite on `__list` and
   `__item` explicitly, so inheritance from the band never reached them — and since
   `currentColor` in a `color` declaration means the value inherited from the
   PARENT, a currentColor mix on the anchor resolved from that Slate Graphite and
   put dark text on Obsidian at 1.25:1. Naming the variable makes the result
   independent of what any ancestor happens to declare. */
.dfx-product-band .dfx-breadcrumbs,
.dfx-product-band .dfx-breadcrumbs__list,
.dfx-product-band .dfx-breadcrumbs__item,
.dfx-product-band .dfx-breadcrumbs__item a,
.dfx-product-band .dfx-breadcrumbs__item + .dfx-breadcrumbs__item::before {
	color: color-mix(in srgb, var(--dfx-band-heading, var(--dfx-signal-white)) 70%, transparent);
}

.dfx-product-band .dfx-breadcrumbs__item a:hover,
.dfx-product-band .dfx-breadcrumbs__item a:focus,
.dfx-product-band .dfx-breadcrumbs__item [aria-current="page"] {
	color: var(--dfx-band-heading, var(--dfx-signal-white));
}

/* Text color inside the band is NOT set here. It is handled alongside the
   builder-row case in the hero's own color rules further down — search for
   "ON DARK, THE INHERITED COLOR IS NOT WHITE". Two dark contexts, one set of
   rules, so the band and a `.light` row cannot drift apart. */

/* No rules for a positioning headline or a built-for line.
 *
 * Both used to render from meta above the_content(). Product pages are built in
 * WPBakery now, so the deck and the audience line are page content — the editor
 * lays them out in the builder, styles them with the builder's own controls, and
 * sees them in place. Styling them from here would mean the top of the page was
 * assembled from two systems at once.
 *
 * The meta fields still exist and are still used, just not on this page: the
 * archive card uses built_for as its subtitle, and the comparison table uses the
 * tier's built_for for the "who is this for" line under each column.
 *
 * Note the card IS now styled — see the Product card surface section further down.
 * .dfx-card--product carries a raised white surface, a hairline, an 8px corner and a
 * two-layer shadow, taken from Socket UI as the agreed style direction, and __body
 * carries the padding and the internal rhythm. __media is the one child still bare,
 * because nothing renders an image on a card yet.
 *
 * __type and __count are gone entirely rather than unstyled. The product type is
 * admin vocabulary and was never something to badge at a buyer; the feature count
 * was a number with no scale to read it against. See card.php for both. */

/* --- Availability badge (front-end) ---------------------------------------- */
/* The admin has its own .dfx-badge in admin-content-model.css using WordPress
   admin colors. This is the marketing-surface equivalent, on brand tokens.

   Color choices are constrained by the three-green rule, so no status green
   appears here at all: `available` is the default state and renders no badge, and
   the remaining states are not terminal positives. Signal is reserved for
   in-flight motion, which a release stage is not.

   Every badge carries its label as text, so the color is reinforcement rather
   than the message.

   THE INCLUSION-LEVEL CHIP USED TO SHARE THIS GEOMETRY by joining the selector list
   below, so radius, size, tracking and padding came from here and the two could not
   drift into looking almost-but-not-quite alike. It is gone: the feature page's
   "How to get it" now renders product cards, and the inclusion level rides in as the
   card's plain-text note rather than as a chip. See `.dfx-card__note`.

   THE FILL CARRIES THE DISTINCTION, and it is a rule rather than a preference:

     colored fill   a status, or a commercial state that costs money
     gray fill       a neutral label — a relationship rather than a lifecycle
     white + border  retired, the one status quiet enough to need an outline

   THE PRODUCT TYPE IS A PARTIAL EXCEPTION, and the history is worth having. It was
   the gray chip on the product card, printing all four types, and it was removed:
   "Simple" and "Tiered" are admin vocabulary, and on the archive the group heading
   already said the same thing in buyer language. See card.php.

   It is back on the product PAGE for `add_on` alone — as `.dfx-badge--relationship`,
   gray, because "bought alongside something else" is a relationship and not a
   lifecycle. dfx_get_product_type_badge() holds the rule and the reasoning for the
   three types that still print nothing.

   The card is unchanged and still prints no type at all — a card sits under a group
   heading that already says Add-ons, and the page it links to does not.

   THE GRAY CHIP AND THE RETIRED BADGE NEVER MEET. `.dfx-badge--retired` renders in
   the tier table, and a retired product's header is the one place the relationship
   chip could in principle land beside it — where gray-on-white and
   white-with-a-border are still two distinguishable things, and both carry their own
   word. This used to be a three-way version of the same argument, the third being
   the inclusion level; that chip no longer exists. */
.dfx-badge {
	display: inline-block;
	margin: 0 0 0.5rem;
	/* Sides widened from 0.625rem. A pill needs more horizontal room than a rectangle
	   did — the curve eats into the space beside the first and last letter, so the same
	   padding that looked balanced with a 2px corner reads as cramped once the ends are
	   round. 0.875rem against 0.25rem top and bottom. */
	padding: 0.25rem 0.875rem;
	/* A PILL, matching Socket UI's chip — which uses border-radius: 999px, and the
	   homepage's own category chips, which are 20px on a 37px-tall pill. 2px was the
	   theme's default corner and made these read as small rectangular tags rather than
	   as chips.

	   999px rather than 50%: a percentage radius on a non-square box gives an ellipse
	   that changes shape with the text length. A large fixed length always resolves to
	   half the height, which is the pill idiom and is stable at any width.

	   THE 2px CORNER SURVIVES ELSEWHERE ON PURPOSE. Buttons, the tier table and the
	   card's own 20px corner are unaffected — this is the badge component only, so the
	   change reaches the card chips, the hero's type chip and the feature page's
	   inclusion levels, which are the four surfaces that should agree. */
	border-radius: 999px;
	font-family: var(--dfx-font-body);
	/* 11px → 12px, the one value in the sweep that went UP. 0.6875rem was the smallest
	   text on the site and below the new scale's floor; the badge idiom survives the
	   extra pixel and 11px did not survive a squint test. */
	font-size: var(--dfx-size-micro);
	font-weight: var(--dfx-weight-emphasis);
	/* NO text-transform, SO THE LABEL RENDERS AS IT IS WRITTEN. These strings come from
	   term names and translated PHP — "Package", "Coming soon", "Add-on" — and forcing
	   caps here meant the CSS was overruling what the content model actually says. It
	   also meant the one place that wanted sentence case, the hero's type chip, had to
	   opt out with `text-transform: none`; that override is now redundant and gone.

	   letter-spacing GOES WITH IT, and that is a consequence rather than a separate
	   choice. 0.08em is caps tracking: uppercase needs the extra room because every
	   letter is the same height and the shapes crowd. Applied to sentence case it just
	   reads loose. If the tracking is wanted back, the case has to come back with it. */
	letter-spacing: normal;
	line-height: 1.5;
	white-space: nowrap;
}

/* Not yet purchasable — Saffron is the brand's caution tone, and "not available
   yet" is exactly a caution on a page whose job is to sell. */
.dfx-badge--coming_soon {
	background: #fdf3e6;
	color: #8a5d0f;
}

/* Available to some customers — Informational Blue, because this is a statement
   of fact about program scope, not a warning. */
.dfx-badge--early_access {
	background: #eaf1fa;
	color: #2c5a8f;
}

/* Reachable by URL but out of the listings. Fully neutral: a retired product
   should not draw the eye. */
.dfx-badge--retired {
	background: var(--dfx-signal-white);
	color: var(--dfx-color-body);
	border: 1px solid var(--dfx-color-border);
}

/* THE CERTIFICATION CHIP — "Preferred 3Synergy partner", on the OEM band only.
   Not an availability status despite riding the hero part's `status` slot: that slot
   is a variant name and a label, and this is the one chip in the set that states a
   credential rather than a lifecycle stage.

   SOLID WHITE ON THE DARK BAND, at 15.6:1. Every status chip above is a light fill
   built for a light page, and reused here they read as one more product label. The
   band carries nothing else in solid white, so this is the only thing on it that
   reads as a seal.

   BRASS WAS THE OTHER CANDIDATE AND IS WRONG HERE. The brand caps it at one moment
   per surface, and on these pages that moment is the CTA further down the page — a
   Brass chip in the band would spend it above the fold on something that is not an
   action. */
.dfx-badge--certification {
	background: var(--dfx-signal-white);
	color: var(--dfx-obsidian);
}

/* THE FEATURED CHIP — "Most popular", and the one place Brass belongs.
   The brand system caps Brass at one moment per surface, which is exactly what a featured
   tier is: the element allows a single one per ladder, so the constraint is enforced by the
   control rather than by remembering the rule. It also separates this chip from the blue
   add-on chips beside it — a claim about what sells, not a statement about scope.

   OBSIDIAN ON BRASS AT 6.78:1, which is the pairing the primary button already uses, so
   the two Brass moments a page can carry agree with each other. The fill measures 2.48:1
   against white, well past the point where a chip reads as a chip, so unlike the add-on
   chip this one is visible by fill as much as by ink.

   The words are the editor's, so this rule sets no content and no width. "Most popular",
   "Best value" and a two-word phrase in French all have to fit. */
.dfx-badge--featured {
	background: var(--dfx-brass);
	color: var(--dfx-obsidian);
}

/* NOTHING FOR .dfx-tier-ladder__card--featured, DELIBERATELY. The class is on the card so
   a page can add emphasis — a ring, a lift, a heavier border — from the element's Design
   Options box, without a stylesheet change. The reference marks its recommended plan with
   a chip and nothing else, and a card that is both tinted by its section and outlined for
   being featured starts competing with the section grouping it sits inside. If a default
   emphasis is ever wanted, this is where it goes. */

/* THE ADD-ON CHIP — one treatment for every place the word appears.
   "Add-on" is printed in four places: the tier ladder's feature list, the comparison
   table's cells, the product card's type chip and the product hero's. Three of them were
   gray and the fourth was muted gray text with no chip at all, so the same commercial fact
   looked like four different things — and on a tinted section the ladder's version
   disappeared into the panel, which is what prompted this.

   BLUE, AND NOT THE OTHER CANDIDATES. Brass is the premium accent and the brand system
   caps it at one moment per surface — a feature list can carry five add-ons, so brass was
   out on the first count. The greens are spoken for by the three-green rule and none of
   them means "you can buy this". The Teal and Violet families are for data visualisation
   and feature differentiation, which is close, but a teal chip beside green ticks reads as
   a status. Informational Blue is the family for a statement of fact about scope, which is
   what an add-on is.

   A STEP DEEPER THAN --early_access, DELIBERATELY. That chip is also blue — #2c5a8f on
   #eaf1fa — and two blue chips meaning different things would be the reuse the palette
   rules warn about. This one is brighter and stronger: blue-100 behind blue-600 from the
   SUI 2.0 ramp, which reads as a live commercial label rather than a muted program note,
   and the two are told apart by depth rather than by hue.

   THE FILL IS SUBTLE AND THE INK IS NOT, which is the honest way to describe it. #C7E3FF
   against white measures 1.32:1, so the fill alone is not what makes the chip visible —
   the blue text at 5.04:1 on the fill is. That is also true of the two status chips above,
   and it is why the ink is the value to protect if either is ever retuned.

   Literals rather than tokens, as the two chips above are, and for the same reason: the
   marketing palette has no surface step at this lightness. If SUI 2.0's blue ramp is ever
   exposed as marketing tokens, these are var() candidates. */
.dfx-badge--add-on {
	background: #C7E3FF;
	color: #005BB3;
}

/* The gray chip — a neutral label rather than a status.

   The fill is a literal rather than a token because there is no token for it: the
   neutral ramp jumps from Signal White (#F5F6F7, the page surface) to Soft Stone
   (#C8CBCF, a border weight), and this needs to sit between them — light enough to
   read as a label, dark enough to separate from a white surface. The two status
   tints beside it are literals for the same reason.

   ONE CHIP USES IT NOW. It was shared with `.dfx-included-in__level`, the feature
   page's Core / Additional / add-on chip, on the reasoning that both answer "what is
   this thing's relationship to something you buy" — which is precisely what the gray
   fill is reserved for — so a second literal #edeff1 would have been the same
   decision written twice and drifting from then on. That chip is gone with the
   `.dfx-included-in` list, so the selector list is down to one name. Kept as its own
   rule rather than folded into `.dfx-badge--add-on` above: the two fills are
   different values answering different questions.

   THE ADD-ON CHIP ALSO READS ON THE DARK BAND, which is where it actually renders:
   the product header band sets a dark background and white heading text, and this
   chip carries its own light fill and its own dark body color, so it is legible
   there for the same reason `.dfx-badge--coming_soon` is. It is not inheriting
   anything from the band, which is what would have made it fragile. */
.dfx-badge--relationship {
	background: #edeff1;
	color: var(--dfx-color-body);
}


/* --- Link arrow ------------------------------------------------------------- */
/* ONE ARROW, THREE PLACES: the product card, the tier comparison table and the
   feature list. Salient's `arrow-animation` — a 25px hairline shaft with a chevron
   head that draws in on hover. Built by dfx_link_with_arrow(), which is a faithful
   copy of the markup nectar_cta.php emits, and where the structure is explained.

   Almost nothing here is ours. The geometry, the positioning, `stroke:
   currentColor` on the head and all seven keyframes are Salient's. What follows is
   the shaft color and two context adjustments.

   THE CHEVRON IS HIDDEN AT REST — `ctaArrowEnd` finishes at opacity 0 and
   `ctaArrowStart` draws it back on hover — so the resting mark everywhere is the
   shaft alone. On the card that is the intended reveal. On a feature row the shaft
   is doing real work: only standalone features have a page, so it is what separates
   a linked row from an unlinked one at a glance. If that distinction ever needs to
   read harder, override the polyline animation for those two contexts rather than
   swapping in a different arrow.

   It is not Font Awesome any more. The old glyph was fa-long-arrow-right (\f178),
   picked because FA4 ships one weight so the lightest mark had to come from the
   lightest-drawn glyph. The note here used to say the next step past that was "an
   inline SVG with an explicit stroke-width, not another icon font" — which is
   exactly what Salient already shipped and this had missed.

   WHY THIS IS SAFE TO HAND-WRITE WHERE nectar_badge IS NOT: every rule lives in
   stylesheets Salient enqueues unconditionally — selectors in css/build/style.css,
   keyframes in css/build/style-non-critical.css. nectar_badge's CSS is emitted
   per-page by class-nectar-element-styles.php only when it finds that shortcode in
   post_content. Checked both before choosing. */

/* THE SHAFT FOLLOWS THE LABEL'S COLOR. The one override `arrow-animation` needs,
   and it is a Salient gap rather than a preference: the chevron head is
   `stroke: currentColor` in their own rule, but the shaft is a separate element
   painted with `background-color: #000`, switching to #fff only under a `.light`
   ancestor. Left alone, a Baltic label trails a black shaft — two colors on one
   arrow. currentColor makes the shaft do what the head already does, so the whole
   link recolors as one thing on hover.

   THE SELECTOR IS LONG ON PURPOSE — 0,4,0. It has to clear TWO Salient rules, and
   a plain `.dfx-card__cta .line` at 0,2,0 cleared neither:
     .nectar-cta[data-style=arrow-animation] .line          0,3,0
     .light .nectar-cta[data-style=arrow-animation] .line   0,4,0
   The second decides the length. It ties at 0,4,0, so source order settles it and
   ours is in a stylesheet enqueued after Salient's — but the tie is deliberate
   rather than lucky: going higher would mean naming an ancestor of every context
   this arrow appears in, and there are now three. */
.nectar-cta[data-style="arrow-animation"] .dfx-card__cta .line,
.nectar-cta[data-style="arrow-animation"] .dfx-feature-link .line,
.nectar-cta[data-style="arrow-animation"] .dfx-tier-ladder__compare .line {
	background-color: currentColor;
}

/* BOTH LINKS ARE inline-block, NOT inline-flex. Salient gives `.text` inside the
   anchor `display: block` and positions the arrow absolutely against the anchor's
   padding box, so the anchor has to be a block container for either to resolve. A
   flex container would make the label and the arrow flex items and take the
   absolute positioning off its reference. */
.dfx-card__cta,
.dfx-feature-link,
.dfx-tier-ladder__compare {
	display: inline-block;
	/* Shared, so the three links cannot end up transitioning differently. Color only
	   — the shaft and head motion is Salient's, driven by its own keyframes. */
	transition: color 0.15s ease;
}

/* NO UNDERLINE ON EITHER, unlike most links in this theme. `.link_text` carries
   ~40px of padding on the arrow's side to reserve room for it, and an underline
   spans the padding box — so the rule would run out from under the last word and
   stop halfway beneath the arrow.

   Color is still not the only signal, which is what the underline was doing
   elsewhere: the shaft is visible at rest and the head draws in on hover, so the
   affordance is a mark rather than a hue. */
.dfx-card__cta,
.dfx-card__cta:hover,
.dfx-card__cta:focus,
.dfx-feature-link,
.dfx-feature-link:hover,
.dfx-feature-link:focus,
.dfx-tier-ladder__compare,
.dfx-tier-ladder__compare:hover,
.dfx-tier-ladder__compare:focus {
	text-decoration: none;
}

/* FEATURE LINKS GET BALTIC, and here it is not only the text: the shaft inherits the
   color through the rule above, and WCAG 1.4.11 asks 3:1 of a graphic that identifies
   a control — the shaft is what marks which of thirty rows lead somewhere.
   --dfx-color-link is AA on white only (4.33:1 on the surface, DSGN-618). Baltic is
   8.46:1 and needs no new token; scoped here, since repointing the token would repaint
   every link on the site. */
.dfx-feature-link {
	color: var(--dfx-color-brand);
}

.dfx-feature-link:hover,
.dfx-feature-link:focus {
	color: var(--dfx-color-text);
}

/* --- Product card ----------------------------------------------------------- */
/* The parts that are not the surface. .dfx-card--product, __body and __built-for are
   handled in the Product card surface section further down; __media is still
   unstyled, because no card renders an image yet.

   THERE IS NO .dfx-card__meta ANY MORE. It was a flex row holding the type chip and
   the availability badge; the type chip went (admin vocabulary), and then the badge
   moved into the title line, so the row had nothing left to hold. Removed from the
   markup rather than left as an empty wrapper.

   THE BADGE IN THE TITLE IS WHAT FIXES ALIGNMENT ACROSS A ROW OF CARDS. On its own
   row the badge rendered only for products that are not available, so every card
   carrying one pushed its title a row lower than its neighbours. Titles are the
   strongest horizontal line in a grid of cards, and they were not lining up.

   SMALLER HERE, AND ONLY HERE. The badge is 0.6875rem — 11px — everywhere else, and
   that is right in its other three contexts: the header band, the tier table header
   and the feature index all use it as a label sitting beside or above a larger block,
   where 11px reads as small print. In a card title it is inline with the type it sits
   next to, and 11px against the card title is most of its size — near enough to
   compete with the product name rather than annotate it.

   SIZED IN em, SO IT IS A RATIO RATHER THAN ANOTHER MAGIC NUMBER. 0.6em of the
   title, which is 1.125rem via `.dfx-h5`, so about 10.8px today — and this is the
   mechanism working: the heading step moved from 16px to 18px in brand-tokens.css and
   the chip followed on its own instead of drifting out of proportion.
   The padding is em for the same reason: it scales with the chip, not with the root.

   `font-size` is the one number to nudge if this still is not right. 0.6em is about
   as small as uppercase at 0.08em tracking stays comfortable; below roughly 9px it
   starts reading as fine print rather than a label.

   If it should be smaller in every context rather than this one, the place to change
   is `font-size` on the shared `.dfx-badge` rule above, and this override then wants
   deleting rather than adjusting.

   Nothing else is restated: .dfx-badge already sets its own family, weight, tracking,
   uppercasing and `white-space: nowrap`, and a property set on the element itself
   beats anything inherited from the heading around it. */
/* THE TITLE LINK TAKES THE HEADING'S COLOR, and this is what actually made the title
   invisible on the dark card — not the heading rule, which was already fixed.

   The h3 computed to Signal White correctly. Inside it, the <a> was painting itself
   rgb(20, 30, 44) — Obsidian, the card's own background — so the text was there, sized
   and visible, in exactly the color of the thing behind it. Measuring the heading said
   the fix had worked; measuring the anchor said otherwise.

   THE SOURCE IS Salient's GENERATED FILE AGAIN: `body a { color: … }` at 0-0-2 in
   salient-dynamic-styles.css, from the Theme Options link color, which on this site is
   set to Obsidian. brand-base.css declares `a { color: var(--dfx-color-link) }` at 0-0-1
   and loses to it site-wide — worth knowing separately, but here it means the card had
   to name the anchor itself. Third time the generated file has decided a card question.

   `inherit`, not a literal. The anchor then follows whatever the heading is, so if the
   card ever goes light again this needs no second edit. 0-1-1, which clears the 0-0-2.

   Brass on hover, matching the Learn more link's resting color, so the card has one
   accent rather than two. 6.78:1 on Obsidian. */
/* THE OVERFLOW GUARD IS PAIRED WITH THE GRID'S 17rem FLOOR, and it is the half that
   catches what a floor cannot. A definite floor stops a title pushing its TRACK wider
   than its share; it does nothing about a single word wider than the card, which
   overflows the fill and prints on the page behind it — "Scheduling" hanging out of a
   105px card is how the constrained-column bug was first reported. break-word rather
   than anywhere, so wrapping stays at word boundaries until a word genuinely will not
   fit. Cheap, and it makes the card safe at any width a caller hands it. */
.dfx-card__title {
	overflow-wrap: break-word;
}

.dfx-card__title a {
	color: inherit;
	text-decoration: none;
	/* THE GAP BEFORE THE BADGE LIVES HERE, not as a left margin on the badge, and that
	   is the fix for a badge that wrapped to its own line sitting ~12px indented from
	   the title. A leading margin still renders at the start of a wrapped line; a
	   trailing one on the element before it does not. 0.667em of the 18px h5 step = the
	   same 12px as before. */
	margin-inline-end: 0.667em;
}

.dfx-card__title a:hover,
.dfx-card__title a:focus {
	color: var(--dfx-brass);
}

/* SHARED WITH .dfx-feature-index__name BELOW, so the two title lines that carry chips
   size and space them identically. Everything in the rule is em-relative, so the 18px card
   title and the 16px feature name each get a chip in proportion without a second block.
   Only the Powder repaint above stays card-only — that one exists for a DARK surface, and
   the feature card is light. */

/* THE TYPE CHIP TAKES THE REFERENCE'S POWDER PILL. Scoped to the card rather than to
   .dfx-badge--relationship globally, which would also repaint the product page's Add-on
   chip and the feature page's inclusion levels — both of which sit on light surfaces
   where #edeff1 is correct. Obsidian on Powder is 8.7:1.

   The STATUS badges are left alone. coming_soon, early_access and retired are all light
   fills with dark text, so they read on a dark card exactly as the reference's chip does;
   inverting them would have meant inventing three new pairs for no gain. */
.dfx-card__title .dfx-badge--relationship {
	background: var(--dfx-powder);
	color: var(--dfx-obsidian);
}

.dfx-card__title .dfx-badge,
.dfx-feature-index__name .dfx-badge {
	/* FLOORED AT THE MICRO STEP, because 0.6em alone now undershoots the scale. Against
	   the 18px h5 card title this resolved to 10.8px — the only text on a product page
	   below the body scale's 12px floor, found by probing rather than by reading, since
	   nothing here states a size you can grep for. max() keeps the em relationship the
	   padding and margin below depend on (they resolve against this element's own size,
	   so all three still move together) while refusing to go under the floor. If the
	   card title ever rises above 20px the em term takes over again. */
	font-size: max(var(--dfx-size-micro), 0.6em);
	/* 1.25em of side padding, matching the ratio the shared rule now uses — 0.875rem
	   against an 11px font. Stated in em rather than rem because this chip is sized in
	   em too, so the two move together instead of the padding staying fixed while the
	   text scales with the title. */
	padding: 0.25em 1.25em;
	/* The badge's own `margin: 0 0 0.5rem` is for the stacked contexts it was built for —
	   the product header band, the tier table header. Here it sits in the title line.

	   ALL SPACING TRAILS, NONE LEADS. A left margin survives a line break, which is what
	   indented a wrapped badge by 12px; the title's own `margin-inline-end` supplies that
	   gap now. The between-chips gap is the rule below. */
	margin: 0;
	/* Against the title's lowercase rather than its baseline, which is what stops an
	   uppercase chip sitting low beside the card title. */
	vertical-align: middle;
}

/* THE SEPARATOR BETWEEN TWO CHIPS, AND `:not(:last-child)` IS LOAD-BEARING RATHER THAN
   TIDY. This was an unconditional `margin-inline-end: 1em`, described as "invisible on the
   last badge in the line" — which it is to look at and is not to lay out. Trailing margin
   still occupies inline space, so it counts toward the line's width: on a 250px feature card
   an "Alignment & Tread" name plus one chip came to 96.7px against 97px of room and the chip
   wrapped to its own line. The gap it was reserving was after the last thing on the line,
   where nothing needed separating.

   Scoped to a chip that is FOLLOWED by another, which is the only case the 1em was ever for
   — coming soon AND add-on. Trailing rather than leading for the reason above it: a leading
   margin renders at the start of a wrapped line and indents the chip. */
.dfx-card__title .dfx-badge:not(:last-child),
.dfx-feature-index__name .dfx-badge:not(:last-child) {
	margin-inline-end: 1em;
}

/* "Learn more" — a link, not a button. The card is an invitation to read the
   page, and a filled button on every card in a nine-up grid turns a browse surface
   into a wall of calls to action.

   Baltic for the same contrast reason as the feature links above; display,
   text-decoration and the hover color are all set with them in the Link arrow
   block, since the two links share a structure and should not drift. Only the size
   and the resting color are card-specific. */
.dfx-card__cta {
	/* BRASS, WHICH ONLY WORKS BECAUSE THE CARD IS DARK. It is 6.78:1 on Obsidian and
	   2.29:1 on Signal White — the same figure that got brass pulled off the workflow
	   icons and kept it off the feature links. It is legible here and nowhere else on a
	   light page, so this color must not be lifted out of the card.

	   Baltic was the previous value and is 2.4:1 on Obsidian: AA-passing on white,
	   failing here. The swap is a correctness fix as much as a match to the reference,
	   which uses brass for exactly this link. */
	color: var(--dfx-brass);
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-emphasis);
}

/* Obsidian on hover, at 15.5:1. Cyan-hover was the obvious pairing and is 3.13:1 —
   a hover state that drops below the resting state's contrast is a regression
   dressed as feedback. */
/* White on hover, not Obsidian. The old value was --dfx-color-text, which IS Obsidian —
   the card's own background now, so the link would have vanished on hover. Signal White
   at 15.5:1 is the strongest move available and reads as the arrow lighting up. */
.dfx-card__cta:hover,
.dfx-card__cta:focus {
	color: var(--dfx-signal-white);
}

/* --- Tier comparison table -------------------------------------------------- */
/* NOTHING HERE ON PURPOSE. The table takes Salient's own table styling and nothing of
   ours: 466 lines went, plus 322 for the tier columns as cards and the responsive block
   that sized them. Requested as a clean slate, so what it renders now is the parent
   theme's — `.main-content th`/`td` box every cell with a #ececec right and bottom
   border, `tr td:first-child` adds a left one, `table tr:nth-child(2n+1)` stripes at
   #fcfcfc, and `caption, td, th` set weight 400 and align left.

   WHAT WENT WITH IT, so nobody hunts for a regression: the sticky feature column, the
   fixed table layout and its column tokens, the horizontal scroll wrapper, the workflow
   group row treatment, the tier lane fills and their edges, and the tick and chip
   colors. A table wider than its container now scrolls the PAGE rather than itself.

   The disclosure that reveals the table is further down and stayed — it is the control,
   not the table. Git history has all of it at 0648c1f if any of it is wanted back. */


/* --- Tier comparison disclosure --------------------------------------------------
   The Zendesk pattern from the Project Keystone review: the table behind an underlined
   text link rather than an accordion header. Native <details>, so open and close,
   keyboard and the collapsed-region announcement are the browser's; everything here is
   appearance.

   UNDERLINED, WHICH IS THIS THEME'S NORMAL LINK AND NOT A CHOICE MADE HERE. The two
   links that go without one — .dfx-feature-link and .dfx-tier-ladder__compare — are the
   exceptions, and only because Salient's arrow shaft reserves padding an underline would
   run beneath. There is no shaft here. */
.dfx-tier-comparison__reveal-summary {
	/* BOTH PROPERTIES, AND NEITHER IS REDUNDANT. `display` removes the triangle in Chrome and
	   Firefox; ::-webkit-details-marker below is what Safari reads. */
	display: inline-block;
	list-style: none;
	cursor: pointer;
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-body);
	font-weight: var(--dfx-weight-emphasis);
	color: var(--dfx-color-link);
	transition: color 0.15s ease;
}

.dfx-tier-comparison__reveal-summary::-webkit-details-marker {
	display: none;
}

/* THE UNDERLINE IS ON THE LABEL, NOT THE SUMMARY, so it stops at the words. Decoration
   propagates into ::after and cannot be turned off there, so an underline one level up would
   run beneath the chevron.

   UNDERLINED AT ALL BECAUSE THAT IS THIS THEME'S NORMAL LINK. The two that go without —
   .dfx-feature-link and .dfx-tier-ladder__compare — are the exceptions, and only because
   Salient's arrow shaft reserves padding an underline would run under. */
.dfx-tier-comparison__reveal-label {
	text-decoration: underline;
	/* Keeps the rule off the descenders in "Compare" and "features". */
	text-underline-offset: 0.15em;
}

/* STATES ITS OWN COLOR, so it stays body copy while the summary around it is link blue —
   and stays put through hover, which only moves the summary's own color. Regular weight
   against the label's emphasis is the second half of the same signal: the question is
   context, the link is the thing to click. */
.dfx-tier-comparison__reveal-intro {
	color: var(--dfx-color-body);
	font-weight: var(--dfx-weight-body);
}

.dfx-tier-comparison__reveal-summary:hover,
.dfx-tier-comparison__reveal-summary:focus-visible {
	color: var(--dfx-color-link-hover);
}

/* A REAL FOCUS RING, because the summary is the only focusable thing here and suppressing the
   marker took away the browser's own affordance for it. Salient resets outlines broadly, so
   this states one rather than trusting the default. */
.dfx-tier-comparison__reveal-summary:focus-visible {
	outline: 2px solid var(--dfx-color-link);
	outline-offset: 3px;
}

/* TWO BORDERS ROTATED 45°, WHICH IS THE WHOLE CHEVRON. Drawn rather than set in an icon font
   because Salient re-points its Font Awesome classes at icomoon, so an <i class="fa"> here
   would render a glyph this theme does not control — see the disclosure builder for the
   version that did.

   `display: inline-block` IS LOAD-BEARING: `transform` does not apply to non-replaced inline
   elements, and the failure is silent — the rule matches, the computed value stays `none`.

   currentColor, so the chevron follows the label through hover and focus without a second
   color rule. */
.dfx-tier-comparison__reveal-summary::after {
	content: '';
	display: inline-block;
	width: 0.4em;
	height: 0.4em;
	margin-left: 0.5em;
	/* Lifts the box onto the label's optical center — a rotated square hangs low. */
	vertical-align: 0.14em;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate( 45deg );
	transition: transform 0.15s ease;
}

/* POINTS AT WHAT HAPPENS NEXT: down to open, up once open. -135 rather than 225 so the
   rotation takes the short way round. */
.dfx-tier-comparison__reveal[open] > .dfx-tier-comparison__reveal-summary::after {
	transform: rotate( -135deg );
}

/* ALIGNMENT SITS ON THE <details> AND REACHES THE SUMMARY THROUGH IT. The summary is an
   inline-block, so `text-align` on the summary itself would move nothing — a shrink-wrapped
   box has no slack to align within. Left is the element's own default and has no class.

   THE PANEL RESTATES LEFT, WHICH IS THE PART THAT IS NOT OPTIONAL. text-align inherits, so a
   centered line would center the table's heading, its group labels and its footnote along with
   it — the cells state their own alignment and would survive, which is worse than if none of
   it did: half the table would follow and half would not. */
.dfx-tier-comparison__reveal--center {
	text-align: center;
}

.dfx-tier-comparison__reveal--right {
	text-align: right;
}

/* THE SPACE BELOW THE SUMMARY IS INSIDE THE ANIMATED BOX, which is padding on the panel
   rather than a margin under the summary.

   It was `[open] > summary { margin-bottom: 1.5rem }`, and that state flips in a single
   frame: collapsing, the gap vanished while the table was still closing, so the summary
   jumped down onto a table that was still there. Inside `::details-content` the space is
   part of the height being animated, so it grows and shrinks with the reveal — and it is
   absent when closed for free, which is what the two-state rule was for. */
.dfx-tier-comparison__reveal > .dfx-tier-comparison {
	padding-top: 1.5rem;
	text-align: left;
}

/* IT REVEALS NOW, RATHER THAN APPEARING. A native <details> snaps: the panel is
   `content-visibility: hidden` closed and laid out open, with nothing in between, so a
   34-row table arrived in one frame and the page jumped under the reader's eye.

   `::details-content` IS THE PANEL AS ONE BOX, which is what makes this possible without
   a wrapper div or a line of JS — the element's markup is a summary and a bare
   .dfx-tier-comparison, and there was nothing else to animate. Height goes from 0 to
   `auto`, `interpolate-size` is what lets a keyword be an animation endpoint, and
   content-visibility is transitioned `allow-discrete` so the panel stays rendered for the
   duration instead of vanishing on frame one.

   SET ON THE ELEMENT, NOT :root. interpolate-size inherits, and switching it on globally
   would quietly make every `auto` height on the site animatable — a much larger promise
   than this panel needs.

   WHERE IT IS NOT SUPPORTED, IT SNAPS, which is exactly today's behaviour. Chromium has
   both properties; Safari and Firefox are partway, so this is progressive enhancement and
   needs no fallback.

   350ms: long enough to read as a movement on a tall panel, short enough that a reader who
   knows what they want is not waiting for it. */
.dfx-tier-comparison__reveal {
	interpolate-size: allow-keywords;
}

.dfx-tier-comparison__reveal::details-content {
	block-size: 0;
	overflow: hidden;
	transition:
		block-size 350ms ease,
		content-visibility 350ms allow-discrete;
}

.dfx-tier-comparison__reveal[open]::details-content {
	block-size: auto;
}

@media (prefers-reduced-motion: reduce) {

	.dfx-tier-comparison__reveal-summary,
	.dfx-tier-comparison__reveal-summary::after {
		transition: none;
	}

	/* The panel still has to open — only the movement goes. */
	.dfx-tier-comparison__reveal::details-content {
		transition: none;
	}
}





/* --- Product hero ----------------------------------------------------------- */
/* One column's worth of copy, rendered by the Product Hero element.

   OWNS NO LAYOUT, NO BACKGROUND AND NO COLOR OF ITS OWN. Four drafts got here,
   each by giving something back to the stack that already had it:

     1. A 100vw negative margin to escape the container  →  the row full-bleeds.
     2. Its own two-column grid, ratio and alignment     →  the row has columns.
     3. Hand-rolled button markup and hover CSS          →  nectar_btn.
     4. A light/dark text_scheme param                   →  see COLOR below.

   COLOR IS INHERITED. Salient's row already has a Text Color setting, and it
   sets color on the row. Asking again on the element meant the same decision in
   two places, which is one place too many — so nothing here declares a color.
   The headline takes the row's color through normal inheritance, and the
   secondary text derives from it with color-mix() rather than naming a value. Put
   the hero on a dark row or a light one and it follows, with nothing to keep in
   sync.

   Only var(--dfx-*) where a color is unavoidable — brand-tokens.css is the only
   place hex lives. */

/* --- Headline and deck --- */
/* Poppins via --dfx-font-display, matching every other H1 on the site. Color is
   deliberately absent: it comes from the row. */
/* DECLARES NO TYPE. Size, weight, family, tracking and line-height all come from
   the heading level, in brand-base.css — including the fluid clamp, which moved
   there so every h1 scales rather than just this one.
   Consequence worth knowing: the hero element can be set to render an h2 instead of
   an h1, and when it is, this heading drops from the h1 step to the h2 one — 48px to
   32px at full width today. That is the rule working, not a bug: the outline and the
   size are the same decision now. Both numbers come from the scale, so read them from
   brand-tokens.css rather than trusting this line after the next re-anchor. */
.dfx-hero__title {
	margin: 0;
	text-wrap: balance;
	color: inherit;
}

/* Secondary text, derived from whatever the row set rather than declared. 74%
   of the inherited color reads as supporting on a dark row and on a light one,
   which a fixed Powder or Slate value could not do. */
.dfx-hero__eyebrow,
.dfx-hero__subhead,
.dfx-hero__reassurance {
	color: color-mix(in srgb, currentColor 74%, transparent);
}

/* ON DARK, THE INHERITED COLOR IS NOT WHITE.
   Salient's Text Color → Light resolves to #9AA0A6 on `.row_col_wrap.light`, a
   muted gray meant for body copy. Inherited straight through, it left the
   headline and the product name looking switched off.

   So the two identifying lines are pinned to white and everything else still
   derives from them: the subhead and reassurance stay at 74%, which now reads as
   74% of white rather than 74% of gray. The light-row rule sets it on .dfx-hero
   rather than on the title, so `color: inherit` above keeps working and there is
   one place to change.

   Two selectors because there are two dark contexts and neither implies the
   other — `.light` is Salient's builder row, `.dfx-product-band` is the template
   default, which has no Salient row to carry a class.

   The two also diverge on WHAT the color is, which is why they are not one
   selector list: a Salient `.light` row is light-on-dark by definition, so white is
   correct there, while the band is themeable and has to use its own variable. */
.light .dfx-hero {
	color: var(--dfx-signal-white);
}

.dfx-product-band .dfx-hero {
	color: var(--dfx-band-heading, var(--dfx-signal-white));
}

/* The headline needs the extra `.dfx-hero` in the selector, and it is not
   redundant. The parent theme styles headings inside a light row by element —
   `.light h1` — which is one class plus one type, and that outweighs the single
   class of `.dfx-hero__title`. So `color: inherit` lost to Salient's gray even with
   .dfx-hero set to white. Three classes settles it without !important. */
.light .dfx-hero .dfx-hero__title,
.light .dfx-hero .dfx-hero__eyebrow {
	color: var(--dfx-signal-white);
}

/* The product name is identification, not supporting text, so the eyebrow does not
   take the 74% treatment — it matches the headline. */
.dfx-product-band .dfx-hero .dfx-hero__title,
.dfx-product-band .dfx-hero .dfx-hero__eyebrow {
	color: var(--dfx-band-heading, var(--dfx-signal-white));
}

/* The subheading takes its own color when one has been chosen, and otherwise
   DERIVES from the heading at 74% — the same treatment the hero has always used.
   Written as a fallback chain rather than two rules so the derived case needs no
   marker class and no PHP branch: an unset subheading simply has no custom
   property, and the mix behind it takes over.

   Deriving is the better default, not a lesser one. A fixed subheading color has
   to be re-picked every time the heading or the background moves; 74% of the
   heading follows both on its own, on a dark surface and a light one. */
.dfx-product-band .dfx-hero .dfx-hero__subhead,
.dfx-product-band .dfx-hero .dfx-hero__reassurance {
	color: var(
		--dfx-band-subhead,
		color-mix(in srgb, var(--dfx-band-heading, var(--dfx-signal-white)) 74%, transparent)
	);
}

/* TYPE COMES FROM .dfx-lead, which hero.php also puts on this element — the brand
   layer's lead/subtitle role in brand-base.css. The four declarations that used to
   be here (body font, 1.1875rem, body weight, body line-height) were a near-copy of
   it, and because components.css loads after brand-base they would have won and the
   class would have been decorative. Only spacing is ours now. */
.dfx-hero__subhead {
	margin: 1.25rem 0 0;
}

/* A reading measure, not a layout width — the column already decides how wide
   the block is. Set "Line length" to Full when the column is narrow enough that
   this only adds a ragged right edge.

   36ch, MATCHING THE PAGE TITLE, and it was 22ch. The site has two h1 addresses —
   Salient's page header on builder Pages, this hero on every product, workflow,
   feature and integration-type page — and they were measured at 36ch and 22ch, so the
   same rank of heading wrapped at two different widths depending on which template
   drew it. brand-base.css owns the 36ch for the page header; this is the third place
   that figure appears, and all three move together. */
.dfx-hero--measure-constrained .dfx-hero__title {
	max-width: 36ch;
}

.dfx-hero--measure-constrained .dfx-hero__subhead {
	max-width: 52ch;
}

/* .dfx-lead carries a 66ch reading measure of its own, which would quietly reinstate
   a limit on the one setting whose whole purpose is removing it. Line length → Full
   has to mean full. */
.dfx-hero--measure-full .dfx-hero__subhead {
	max-width: none;
}

/* --- Eyebrow: the product name, typed as an H4 --- */
/* WEIGHT AND TRACKING NOW COME FROM THE TOKENS, and this is the change the previous
   version of this comment asked for.
   It used to hardcode weight 500 and -0.02em — Salient's generated `body h4` values
   — because brand-base's bare `h4` rule at 0-0-1 lost to them, so a real H4 rendered
   500 and an eyebrow built from the h4 weight token looked visibly heavier than
   the H4s beside it. The note ended: "If the heading scale is ever escalated to
   `body h4` specificity so the brand tokens win, these three lines should go back to
   the variables."
   That escalation exists now — brand-base.css declares `body h4, .row .col h4,
   .wpb_wrapper h4 { font-weight: var(--dfx-weight-heading-light) }` at 0-0-2 / 0-2-1 —
   so this element and a real H4 render the same weight whatever the token says, which
   is the whole point of reading it. That token is 500 today, so both are 500; the
   hardcoded 500 this rule replaced would have been accidentally right and would have
   drifted the moment the token moved, which is the difference worth keeping.
   LETTER-SPACING follows the token, and the caveat that used to sit here is gone:
   tracking is now escalated in brand-base alongside weight, so a real H4 computes
   -0.01em from the same token instead of Salient's -0.02em. The two agree by
   construction rather than by a rounding argument. See the NOTE in brand-base.css.
   FONT-SIZE READS --dfx-size-h4 rather than restating it. It was a literal 1.5rem
   with a comment asking the next person to keep it in step with the h4 step by hand,
   which the ramp change would have broken silently — the scale moved to 20px and an
   eyebrow pinned at 24px would have ended up LARGER than the section headings it is
   matched to. This is a <p>, so the block's "no font-size on a heading" rule does
   not apply; reading the token is the point, not the exemption.

   Still a <p> in the markup. It sits above the <h1>, so an <h4> element here would
   put the document outline out of order for a screen reader or a crawler, to buy an
   effect CSS gives for free.

   text-transform and the wide tracking are switched OFF rather than simply omitted,
   because this rule previously styled a 12px label: both exist to make 12px legible
   and at 24px they only shout. Dropping the transform also lets the name render as
   written — "Service Intelligence Platform", the capitalisation the brand uses — instead of being
   flattened to ONE PLATFORM by the stylesheet. */
.dfx-hero__eyebrow {
	display: flex;
	align-items: center;
	gap: 0.625rem;
	/* Tight to the headline it labels. 1.125rem read as a gap between two
	   separate things rather than as a label attached to one. */
	margin: 0 0 0.5rem;
	font-family: var(--dfx-font-heading);
	font-size: var(--dfx-size-h4); /* matched to a real h4, via the one token */
	font-weight: var(--dfx-weight-heading-light);
	/* THE h4 BAND, not the shared token it used to read. Tracking split into four bands
	   in this pass and --dfx-letter-spacing-heading now means h2/h3 at -0.02em, so
	   leaving this line alone would have quietly doubled the tracking on an element whose
	   entire job is to match a real h4. Exactly the drift the comment below warns about,
	   arriving via a token rename rather than a missing property. */
	letter-spacing: var(--dfx-letter-spacing-heading-small);
	/* Matched to a real h4 on leading as well as size and weight. This is a <p>, so the
	   size scale in brand-base.css does not reach it — every property it borrows from h4
	   has to be named here, and leaving one behind is how it would drift. */
	line-height: var(--dfx-line-height-heading-small);
	text-transform: none;
}

/* The one place a color is named, because the badge behind the icon has to hold
   its own against either row treatment rather than derive from it. */
.dfx-hero__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 2rem;
	width: 2rem;
	height: 2rem;
	border-radius: 2px;
	background: var(--dfx-color-action);
	color: var(--dfx-signal-white);
}

.dfx-hero__icon-glyph {
	font-size: 1rem;
	line-height: 1;
}

.dfx-hero__icon-img {
	display: block;
	width: 1.125rem;
	height: 1.125rem;
	object-fit: contain;
}

/* THE MANUFACTURER'S MARK, in the eyebrow slot instead of its name. Only the OEM
   band sends it today — Oem_Page::band_args().

   WHITE BY FILTER ON DARK, NOT BY A SECOND ASSET. brightness(0) flattens every opaque pixel
   to black and preserves alpha, and invert(1) after it gives white — the same
   treatment .dfx-oem-grid--white uses, over the same single transparent SVG each
   term already carries. One asset per manufacturer stays the rule, so a mark
   replaced on the term screen is replaced everywhere.

   IT ASSUMES A DARK MARK, which every OEM term currently holds: a brand-colored or
   black SVG. A mark that is ALREADY WHITE would come out black, since the filter
   reads ink and not intent — the uploads folder has a white set from the old site's
   logo strip, and one of those on a term is the way this breaks. The checkerboard
   preview on the term screen is where that shows up.

   THREE HEIGHT CAPS, AND THEY RUN OPPOSITE TO THE OEM WALL'S. There the wide cap is
   the largest, because a wordmark in a narrow grid cell hits its WIDTH limit first
   and lands under a shared height cap. The band has no width limit — the mark sits
   in a full-container flex row — so nothing holds a 6:1 wordmark back, and a shared
   height would print Toyota at 260px wide beside a 44px GM badge. Here the square
   badge gets the largest cap instead: a wordmark's letters fill their height, a
   roundel's glyph does not, so equal optical weight means unequal boxes.

   Height is SET rather than capped, with width auto. Both are safe on these files —
   the SVGs carry width and height attributes, so the aspect ratio is known before
   load and the row does not reflow — but an explicit height needs no intrinsic size
   at all, which is what an SVG stripped of those attributes would leave. */
.dfx-hero__logo {
	--dfx-hero-logo-h: 2rem; /* wide, the default — see logo_shape() */
	display: inline-flex;
	align-items: center;
}

.dfx-hero__logo--square { --dfx-hero-logo-h: 2.75rem; }
.dfx-hero__logo--mid { --dfx-hero-logo-h: 2.5rem; }

.dfx-hero__logo-img {
	display: block;
	width: auto;
	height: var(--dfx-hero-logo-h);
	max-width: 100%;
}

/* SCOPED TO THE DARK CONTEXTS, the same two the eyebrow's white is scoped to further
   up this file — the band, and any Salient row set to Text Color → Light. On a light
   surface the mark keeps its brand color, which is the correct answer there and the
   reason this is not one unconditional rule on .dfx-hero__logo-img. */
.light .dfx-hero .dfx-hero__logo-img,
.dfx-product-band .dfx-hero .dfx-hero__logo-img {
	filter: brightness(0) invert(1);
}

/* Down a step on phones, where the h1 it labels is fluid and shrinks with the
   viewport. Left alone, the mark would grow relative to the headline it sits above. */
@media (max-width: 690px) {

	.dfx-hero__logo {
		--dfx-hero-logo-h: 1.75rem;
	}

	.dfx-hero__logo--square { --dfx-hero-logo-h: 2.25rem; }
	.dfx-hero__logo--mid { --dfx-hero-logo-h: 2rem; }
}

/* The badge row. Both chips come from the shared .dfx-badge rules; the only thing
   set here is the space they sit in.

   THE ROW OWNS THE BOTTOM MARGIN, NOT THE CHIPS. This was `.dfx-hero .dfx-badge {
   margin: 0 0 1rem }` while the status badge was the only chip that could appear —
   a lone block-level element spacing itself off the headline. With a type chip
   possible beside it, that margin on each child put 1rem between two chips on one
   row and 2rem of stacked margin below them the moment the row wrapped. Moving it
   to the row is what makes the two-chip and one-chip cases measure the same.

   `flex-wrap` and not `nowrap`: `.dfx-badge` sets `white-space: nowrap` on itself,
   so a narrow viewport cannot break either label internally and the row is the only
   thing left that can give. `align-items: center` rather than `baseline` — the chips
   are near-identical heights and centring survives one of them wrapping to a second
   line, where baseline alignment would drag the other chip's text out of line.

   SCOPED TO `.dfx-hero` FOR SPECIFICITY, NOT FOR REACH. The row is a <p>, so it
   inherits a paragraph bottom margin from the theme, and the rule replacing it has to
   outweigh whatever set it. `.dfx-hero__badges` alone is 0-1-0 — enough to beat a bare
   `p` but not a scoped one like `.main-content p`, which is exactly the environment the
   Product Hero ELEMENT renders in, since it sits inside the_content. The rule this
   replaced was `.dfx-hero .dfx-badge` and carried 0-2-0 for the same reason. Keeping
   the weight identical means the two-chip row cannot be spaced differently from the
   one-chip badge it succeeded, in either of the two places a hero appears. */
.dfx-hero .dfx-hero__badges {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin: 0 0 1rem;
}

.dfx-hero .dfx-hero__badges .dfx-badge {
	margin: 0;
}

/* The type chip, in the eyebrow row beside the product name.

   NO LAYOUT OF ITS OWN. `.dfx-hero__eyebrow` is already a flex row with a 0.625rem
   gap — it was built that way for the optional icon — so the chip is a third child and
   the row spaces it. What it does need is to stop shouting.

   IT DROPS THE UPPERCASE AND THE TRACKING, which is the shared badge's whole visual
   signature, and the reason is a decision this line already made. `.dfx-hero__eyebrow`
   below styled a 12px uppercase tracked label until it became a 20px product name, and
   the note there says why both went: they exist to make 12px legible, and at 20px they
   only shout — dropping the transform also lets the name render as it is written, "ONE
   Platform" rather than ONE PLATFORM. An uppercase chip on that same line puts the
   treatment straight back, six inches from the name it was removed from, and reads as a
   system tag stuck onto a sentence rather than part of it. "Add-on" also loses its
   hyphen to caps: ADD-ON reads as two tokens joined by a dash.

   So the chip says Add-on, spelled as the taxonomy spells it. The pill still carries
   the label — fill, radius, weight and family all still come from `.dfx-badge`, so it
   is recognizably the same component as the status badge on a card. Only the two
   properties tuned for 11px in a stacked column are overridden for 13px inline.

   13px, not the shared 11px: sentence case reads smaller than caps at the same size,
   and this sits beside the eyebrow, which takes the h4 step — 20px semibold today,
   20px when this was tuned. The pill did not follow, because 13px was chosen against
   caps-versus-sentence-case rather than as a ratio of its neighbour; worth re-checking
   if the h4 step moves much further. Padding stays in `em` so the pill keeps its
   proportions at whatever size it lands on.

   THE SHARED BOTTOM MARGIN COMES OFF TOO. `.dfx-badge` carries `margin: 0 0 0.5rem`
   for surfaces that drop a badge into normal flow. In a center-aligned flex row it
   pushes nothing down — it just makes the row half a rem taller than its content and
   lifts the chip off the name's optical center. */
/* THE SEPARATOR BETWEEN THE FAMILY AND THE PRODUCT NAME — 12px each side.

   margin, on an element, because there was no other way to get at it. The separator was
   a literal " · " inside one escaped string: nothing to select, and the obvious CSS
   answer of word-spacing on the eyebrow would have pushed "ONE" off "Platform" by the
   same amount. Hero::eyebrow_html() wraps the character so this rule has a box.

   0.75rem rather than 12px, which is the same measurement in the unit the rest of this
   file uses.

   INLINE INSIDE .dfx-hero__eyebrow-text, NOT A CHILD OF THE FLEX ROW, and that is why
   this margin is the whole of the gap. `.dfx-hero__eyebrow` is a flex container with
   gap: 0.625rem for the type chip; a separator at that level would collect the gap as
   well as this margin and the space would be 10px + 12px. Inside the text wrapper it is
   an ordinary inline box.

   No color of its own. It takes the eyebrow's, which is what makes it read as
   punctuation rather than as a third thing in the line. */
.dfx-hero__eyebrow-sep {
	margin: 0 0.75rem;
}

/* letter-spacing and text-transform are NO LONGER RESTATED HERE. This chip was the one
   surface that wanted sentence case, so it opted out of the shared rule's uppercase and
   caps tracking; the shared rule no longer forces either, so both overrides said
   nothing. Only the size, the margin and the side padding are still this chip's own. */
.dfx-hero__eyebrow .dfx-hero__type {
	margin: 0;
	font-size: var(--dfx-size-caption);
	padding: 0.25em 1.25em;
}

/* --- Buttons --- */
/* The buttons themselves are nectar_btn, so there are no rules for their
   appearance — Salient styles them, animates them and updates them. This is only
   the row they sit in.

   nectar_btn wraps each button in its own block-level div, so a flex row with a
   gap is what puts them side by side; without it they stack. Salient's own
   margin params still work, and are what to reach for before adding anything
   here. */
.dfx-hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.875rem;
	margin-top: 2.125rem;
}

/* Salient's button wrappers carry their own bottom margin for stacked use, which
   double-counts against the flex gap. */
.dfx-hero__actions > *,
.dfx-hero__actions .nectar-button {
	margin-top: 0;
	margin-bottom: 0;
}

/* Fallback only, for when nectar_btn is unavailable — Hero::button() emits a
   plain anchor with this class and the theme should still look deliberate. */
.dfx-hero__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 3.25rem;
	padding: 0.875rem 1.875rem;
	border-radius: 2px;
	background: var(--dfx-color-action);
	color: var(--dfx-obsidian);
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-body);
	font-weight: var(--dfx-weight-emphasis);
	line-height: 1.2;
	text-decoration: none;
}

.dfx-hero__reassurance {
	margin: 1.125rem 0 0;
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-caption);
	line-height: 1.5;
}

@media (max-width: 782px) {
	.dfx-hero__actions {
		flex-direction: column;
		align-items: stretch;
	}

	/* Stretching the column stretches Salient's anchor, which is display:block with
	   no text-align of its own — so the label stayed at the left edge of a pill
	   running the full measure. Centering the text is the whole fix: the anchor is
	   not a flex container, so justify-content would do nothing, and nothing in
	   Salient sets text-align on .nectar-button for this to fight. */
	.dfx-hero__actions .nectar-button {
		text-align: center;
	}
}

/* =========================================================================
   WORKFLOW GRID
   ==========================================================================

   The three-column icon + name + one-liner grid on a product page, rendered by
   template-parts/product/workflow-grid.php.

   CSS Grid with auto-fit rather than fixed columns and media queries. The column
   count set in the builder becomes a MAXIMUM, applied as a cap on the track size
   by the --cols-* classes below, and auto-fit collapses beneath that cap as the
   container narrows — which matters because
   this element sits inside a WPBakery column of unknown width, so a viewport
   media query would be measuring the wrong thing. A three-column grid dropped
   into a half-width row should reflow, and the viewport has not changed.

   minmax(15rem, 1fr) is the floor: below about 15rem a two-word workflow name
   wraps mid-name, which reads as broken rather than as narrow.
   ====================================================================== */

.dfx-workflow-grid {
	margin: 0 0 3rem;
}

/* SECTION TITLES — the workflow grid's and the tier comparison's.
   Grouped so the two sections a product page can show carry an identical label.

   Spacing and color only. The type comes from the dfx-h4 utility on the element,
   paired with whichever level the template set. An earlier version of this rule
   declared 1rem, the body emphasis weight and letter-spacing 0, which rendered a
   16px h2 — a section label wearing a level it did not look like. If the size is
   wrong, the answer is a different level or a different pairing, not a font-size
   here.

   THE HAIRLINE IS A PSEUDO-ELEMENT, NOT AN <hr> AND NOT A BORDER. It is decoration
   beside a label rather than a thematic break, so it stays out of the markup and out
   of the document outline — that part has never changed.

   BUT IT IS BACK BESIDE THE LABEL, WHICH REVERSES WHAT THIS COMMENT USED TO SAY, and
   the reversal is deliberate rather than a regression. The rule ran inline once, was
   moved to border-bottom because "the line started at a different place on every
   section and moved as soon as anyone retitled one", and is now inline again because
   that behavior is the requested design and not a defect: a rule that begins where the
   words end is the point of the pattern. Nobody should read the old objection in the
   git history and quietly restore the border.

   What the old objection got right is that this needs a flex context to work at all, so
   the alignment now depends on the box rather than being guaranteed by it. Two guards
   follow from that. `align-items: center` puts the line on the optical middle of the
   label — including when a long title wraps, where it centers on the whole block rather
   than tracking the first line. And `flex: 1` with `height: 1px` rather than a border on
   the pseudo-element, so the line owns its thickness and cannot inherit a border color
   from anywhere.

   THE 36ch CAP EXEMPTION IS LOAD-BEARING FOR THIS PATTERN, where before it was a
   correction — and it lives in brand-base.css beside the cap now, not further down this
   file. brand-base.css caps h1–h3 inside .container-wrap at 36ch and exempts component
   titles from it; with a border, that cap cropped the line to the width of a headline,
   which is what the exemption was originally written to fix. With a flex fill it would
   crop the flex CONTAINER, so the line would stop at 36ch mid-section with empty space
   beyond it. Same exemption, and it now prevents a worse-looking failure. If the
   `[class*="__title"]` match there is ever narrowed, this is the pattern that breaks.

   gap sets the space between the words and the line — 0.75rem, i.e. the 12px asked for,
   in the file's own unit. margin-bottom then spaces the whole row from the content
   below. NOTE the total gap to that content is now smaller than it was: the old
   treatment stacked 0.875rem of padding plus the line plus 2.5rem, and this is 2.5rem
   alone, because the line no longer sits between them. Left at 2.5rem deliberately —
   it is the same margin as every other section — but this is the number to raise if the
   content now reads as too close. */
.dfx-workflow-grid__title,
.dfx-tier-comparison__title,
.dfx-related__title,
.dfx-faqs__title,
.dfx-feature-single__title,
.dfx-feature-group__title,
.dfx-feature-list__heading,
.dfx-product-section__title,
.dfx-product-family__title,
.dfx-workflow-page__title,
.dfx-integration-type-page__title,
.dfx-family-page__title,
.dfx-integrations-grid__title--group,
.dfx-forms__title--group {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin: 0 0 2.5rem;
	color: var(--dfx-color-text);
}

/* THE GROUP HEADING IS A LINK ON THE HUB since the type archives exist, and a link
   inside a heading takes Salient's accent color and underline unless told not to. The
   heading rule above owns the color, so this inherits rather than restating it — one
   place to change it. The underline arrives on hover, which is where a heading that
   navigates should announce itself. */
.dfx-integrations-grid__group-link {
	color: inherit;
	text-decoration: none;
}

.dfx-integrations-grid__group-link:hover,
.dfx-integrations-grid__group-link:focus-visible {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

.dfx-workflow-grid__title::after,
.dfx-tier-comparison__title::after,
.dfx-related__title::after,
.dfx-faqs__title::after,
.dfx-feature-single__title::after,
.dfx-feature-group__title::after,
.dfx-feature-list__heading::after,
.dfx-product-section__title::after,
.dfx-product-family__title::after,
.dfx-workflow-page__title::after,
.dfx-integration-type-page__title::after,
.dfx-family-page__title::after,
.dfx-integrations-grid__title--group::after,
.dfx-forms__title--group::after {
	content: "";
	flex: 1 1 auto;
	height: 1px;
	background: var(--dfx-color-border-subtle);
}

/* SUB-GROUP HEADINGS ARE A LABEL, NOT A SMALLER HEADING. "Additional features",
   "Available as add-ons" and "Coming soon" sit under "Core features".

   Two things had to be fixed and the second is why the first was not enough. The shared
   rule gave all four the same full-width hairline, which read as four peer sections and
   undid the ranking the heading levels establish. Removing it then left the heading with
   nothing to distinguish it from the grid beneath: `.dfx-feature__name` was --dfx-size-h5
   in --dfx-font-heading at --dfx-weight-heading in --dfx-color-text, and a heading at
   .dfx-h5 matched it on ALL FOUR — typographically the same object, separated only by
   position. The name has since dropped to h6, so the size no longer collides; the other
   three still do, which is why the treatment stays a difference in kind.

   So this differs in kind rather than degree — smaller, uppercased, tracked and muted at
   once. The treatment is `.dfx-eyebrow`'s, which brand-base.css already defines for
   exactly this role ("small uppercase label above a heading"), applied to a heading
   element rather than the paragraph the eyebrow class assumes. Nothing new is invented;
   an existing voice is reused where the pairing table's "Small label" row points.

   PEWTER, NOT THE EYEBROW'S BRASS. brand-base.css flags brass as low contrast on light
   and it measures 2.31:1 — the same figure that got it removed from the workflow icons.
   Pewter is 4.72:1, clear of the 4.5:1 AA needs for text this size, and it is already
   what secondary means on this page after the icon change. It is also what the h6 label
   step resolves to now, so this reasoning ended up in the token layer rather than here.

   THE LABEL IS STILL SMALLER THAN THE ITEMS, and that was the original argument for
   this rule — 16px from `.dfx-h6` against the 18px item titles. Two pixels is thin, and
   it is no longer what does the work: case is. Uppercase at 0.14em in muted ink against
   sentence-case 600 headings is a difference in kind, and the 2px is incidental to it.
   Worth knowing because the earlier version of this comment leaned on the size gap, and
   that gap has shrunk from 4px to 2px without the rule getting any weaker.

   Letter-spacing is NO LONGER set here. It comes from the h6 label step in
   brand-base.css, along with the transform, the weight and the ink — see the note on
   the shared rule above for what came out and why.

   font-weight CHANGES NOTHING TODAY and is declared anyway, which is worth admitting
   rather than dressing up: --dfx-weight-emphasis and --dfx-weight-heading are both 600,
   and Salient's own `body h3` sets 600 as well. It is here because this is the eyebrow
   role and `.dfx-eyebrow` names --dfx-weight-emphasis, so the two move together if the
   tokens ever diverge. If that reasoning stops being worth a line, delete the line.

   ON SPECIFICITY, checked rather than assumed. Salient's generated styles carry
   `.row .col h3 { letter-spacing: 0; font-size: 1.5rem }` at 0-2-1, which would beat both
   this rule and `.dfx-h6` — and brand-base.css's `.wpb_wrapper h3` at 0-1-1 would take
   the letter-spacing. Neither reaches here: the bands emit their own
   `.container.main-content` outside .container-wrap, with no .row, .col or .wpb_wrapper
   ancestor. That is also why .dfx-h5 was landing at 16px before this change, which is how
   the collision with the item titles was visible at all. Move this list inside builder
   content and both would win.

   NO RULE, AND IT NOW TAKES A PSEUDO-ELEMENT TO SAY SO. This used to read
   `border-bottom: none`, which stopped meaning anything the moment the hairline became
   an ::after on the shared rule above — these headings would have grown a divider back
   without a line of this file changing. `content: none` is the opt-out that matches how
   the line is actually drawn. The old `padding-bottom: 0` went the same way: the shared
   rule no longer sets padding, so overriding it was overriding nothing.

   Margin drops to 1.25rem, which survives from the border era for a reason that still
   holds: 2.5rem was measured against a rule separating two things, and with no rule at
   all the heading has to stay attached to the grid it introduces.

   0-1-0, matching the rule above and winning on source order rather than escalating, so
   this stays overridable in turn.

   SHARED WITH THE PRODUCT ARCHIVE'S FAMILY HEADINGS, declared together rather than
   copied. "Additional features" on a product page and "Service Intelligence Platform" on /products/ are
   the same object: a small label naming the set beneath it, one level under a heading
   that already carries the section's rule. Two rules would drift, and the drift shows up
   as two nearly-identical labels with slightly different tracking.

   Each keeps its own margin below, because what follows differs — a feature grid there,
   a card grid here — so only the type is shared.

   FOUR DECLARATIONS CAME OUT OF HERE, and their absence is the point. This rule used to
   set color, weight, letter-spacing and text-transform to make these read as labels.
   Both elements carry `.dfx-h6`, and the h6 step in brand-base.css is now the LABEL step
   — it owns uppercase, 0.14em, weight 600 and the muted ink for every level and class
   that reaches it. So those four lines were not styling these components, they were
   re-implementing a role that had no single home. Now it has one.

   font-family SURVIVES, and it is the only property here that was ever really local. The
   label role is defined against --dfx-font-body while headings use --dfx-font-heading, and
   these are marked up as headings. Both resolve to different faces today (Inter vs
   Poppins), so this is doing real work rather than restating a default.

   IF THESE EVER LOOK WRONG, look at the h6 label block in brand-base.css first. That is
   the trade this simplification makes: one place to change, one more place to look. */
.dfx-product-group__title {
	font-family: var(--dfx-font-body);
}

/* RESTORING THE LABEL INK THE h6 BLOCK ALREADY ASKED FOR, not choosing a new color.
   This is an `h2.dfx-h6` inside a WPBakery column, so `.row .col h2` in brand-base.css
   scores 0-2-1 with --dfx-heading-ink and beats `.dfx-h6` at 0-1-0 — the kicker rendered
   at full heading strength. The doubled selector is 0-3-0, the same shape used for
   .dfx-integrations-grid__title--group further down.

   --dfx-label-ink, NOT --dfx-color-text-muted: both are Pewter #676E7E on the section's
   Signal White (4.72:1, above AA), but 0-3-0 also outruns `.light .dfx-h6` at 0-1-1, so
   naming the flat token would strand this label at Pewter on a dark band. label-ink
   resolves to 70% of inherited text there. .dfx-product-section has no dark variant
   today; this costs nothing and does not have to be revisited if one arrives. */
.dfx-product-group__title,
.row .col .dfx-product-group__title {
	color: var(--dfx-label-ink);
}

/* NOTHING HERE FOR THE CATEGORY GROUPS ANY MORE, because they are not an accordion any
   more. They were Salient `[toggles]`, and this block carried the two overrides that
   instance needed: a Signal White panel with 2em of air on `.inner-toggle-wrap`, escalated
   to 0-4-3 to clear Salient's own 0-3-2, and a share of the toggle-title size rule further
   down. Both are gone with the component — see feature-list.php for why the accordion went,
   and the feature-list section below for what a category label costs now (one margin).

   IF AN ACCORDION EVER COMES BACK HERE, the escalation is the part worth recovering: a
   plain `.dfx-feature-list .inner-toggle-wrap` at 0-2-0 loses to
   `body .toggle[data-inner-wrap="true"] > div .inner-toggle-wrap`, and a tie on
   specificity would leave the winner to load order. */

/* The commercial state, beside the feature name. Sized down from the standalone chip for
   the reason the tier ladder's copy of this gives: the component is built for a card title
   or a table cell and dominates a list row at its own size. */
/* THE GAP BELONGS TO THE NAME, NOT TO THE BADGE. A margin-left on the chip is the obvious
   way to space them and is wrong at the line break: the margin goes with the chip, so a
   badge that wrapped to its own line started 8px right of the title above it. A trailing
   margin here collapses at the end of a line, which leaves the wrapped badge flush left and
   the inline case unchanged.

   ONLY WHEN A BADGE ACTUALLY FOLLOWS, WHICH IS THE `:has()`. Unconditionally, those 8px
   are inline content on every entry, so a name that fits its column by less than 8px wraps
   anyway — at a 194px track "Two-way appointment sync" measures 184px and broke after
   "appointment" with nothing after it to make room for. Most entries have no badge, so
   most were paying for a gap they did not use.

   `:has()` rather than restructuring the markup, and it is safe to depend on: this
   stylesheet already uses it for the container-wrap padding fix. Where it is unsupported
   the badge simply sits flush, which is a cosmetic loss rather than a broken line. */
.dfx-feature__label:has(+ .dfx-badge) {
	margin-right: 0.5rem;
}

.dfx-feature__state {
	/* ZEROED RATHER THAN UNSET. The shared component carries `margin: 0 0 0.5rem` for the
	   stacked contexts it was written for, which here would only make the row taller than
	   its text. */
	margin: 0;
	padding: 0.05rem 0.5rem;
	white-space: nowrap;
	vertical-align: 0.1em;
}

/* THE HEADLINE MEASURE CAP IS LIFTED IN brand-base.css, NOT HERE ANY MORE, and the
   eight-selector `max-width: none` block that used to sit at this spot is gone.

   What it did still has to happen — brand-base.css caps h1–h3 inside .container-wrap
   at 36ch, about 558px at this size, which cropped the hairline to the width of a
   headline rather than the width of the section. What changed is where. That block
   named these eight titles one by one, so every new component with a section heading
   arrived clipped and got a ninth line added; the accordion on /privacy was about to
   be one. brand-base.css now exempts `[class*="__title"]` beside the cap itself, which
   covers these and anything later named to the same convention.

   NOTHING TO ADD HERE FOR A NEW SECTION TITLE, then, as long as it follows the
   `__title` pattern. If one ever needs a NARROWER measure than full, declare that
   number on the component — the exemption is 0-2-1 and a component rule beats it.

   No equivalent was ever needed for the product bands: they render outside
   .container-wrap, so their headings were never capped. Adding an override there was
   tried and removed, because a rule that fixes nothing still has to be read by
   whoever comes next. */

/* THE WORKFLOW GRID — "What it handles". It shared this rule with the product feature
   list, which sits two bands away on the same page: both were sets of short titled items
   running different track algorithms and row gaps, so they were declared together to stop
   them diverging. They have since diverged on purpose — the feature list is a checklist
   now — and the split is recorded at the foot of this comment.

   FOUR EXPLICIT TRACKS, replacing auto-fit on both. What auto-fit was actually doing
   here was resolving a column count from the container width, which meant neither list
   had a fixed one: at the current measure the workflow grid came out at FIVE columns
   while the feature list came out at four, so the two never matched and nothing in the
   CSS said what either was supposed to be.

   IT ALSO MEANS THE `columns` ARGUMENT NOW WORKS. workflow-grid.php validates that
   parameter against 2, 3 and 4 and emits a --cols-N class, but only --cols-2 ever capped
   anything — it used calc( 50% - 1.25rem ) as the track MAXIMUM, which does cap.
   --cols-4 set minmax( 13rem, 1fr ), which only lowers the floor and still fits five
   columns at this measure, and --cols-3 had no rule at all, so the documented default of
   three silently rendered as four or five. Explicit repeat() counts make the parameter
   mean what it says.

   1fr AND NOT A PERCENTAGE, and minmax( 0, 1fr ) rather than a bare 1fr — see the note
   on the feature list further down, which sets out both. The short version: percentage
   tracks ignore `gap` and overflow, and a bare `1fr` floors at min-content so one long
   name or the nectar-cta block the link arrow renders can push a row past the container.

   Gap is 1em 4em — tight rows, wide columns, so each item reads as a column entry
   rather than a cell in a mesh.

   `.dfx-feature-list__items` IS NO LONGER SHARED HERE, and the split is the point. It rode
   on this rule and on both media queries below, then redeclared itself further down — three
   places to keep in step for one grid, and the note here used to say so. The feature list
   is not a grid of entries at all now — it is one list per column, no rows — while this
   stays four illustrated cells with a summary each. Nothing left to share; its rules live
   in the feature-list section, all of them together. */
.dfx-workflow-grid__items {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1em 4em;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The `columns` argument, as counts rather than as floors. Four is the shared base
   above, so there is no --cols-4 rule here — adding one that repeated the base would be
   a second place to change it. */
.dfx-workflow-grid--cols-2 .dfx-workflow-grid__items {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.dfx-workflow-grid--cols-3 .dfx-workflow-grid__items {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.dfx-workflow-grid .dfx-workflow {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Salient's content styles add a bullet and left padding to li inside .container
   — reset locally rather than fighting it further up the tree. */
.dfx-workflow-grid .dfx-workflow::before {
	content: none;
}

/* The cell body. A plain block wrapper — nothing in this grid links any more, see
   the note in workflow-grid.php.

   It was `.dfx-workflow__link`, an anchor around the whole cell, and it carried
   `text-decoration: none` plus hover and focus-visible states. All of that is gone
   with the anchor:

     · the underline reset is moot, and was losing anyway. Theme Options emits
       `.wpb_text_column a { text-decoration: underline }` at 0-1-1 into
       uploads/salient/salient-dynamic-styles.css, which beat a bare
       `.dfx-workflow__link` at 0-1-0 whenever the element sat in a Text Block — which
       is how the shortcode is normally placed. Worth remembering for anything here
       that IS a link: two classes, or a class plus an element, to clear that 0-1-1.
     · the hover states had to go rather than be kept. `:hover` fires on a div just as
       readily as on an anchor, so leaving them would have colored the name on
       mouseover and promised a click that no longer happens.
     · `:focus-visible` went because a div is not focusable. */
.dfx-workflow-grid .dfx-workflow__body {
	display: block;
	color: inherit;
}

/* THE BODY COPY'S COLOR — Pewter, via --dfx-color-text-muted, which is the token
   `.dfx-workflow__summary` uses.

   THIS DELIBERATELY UNPAIRS THE ICON FROM THE NAME, and it is worth saying so because
   the previous note here argued the opposite: it had the glyph matching
   `.dfx-workflow__name` exactly, on the grounds that the cell should read as one object
   in one color. Two colors in the cell turned out to be the point. The name is the
   heading, the summary is the copy, and a glyph at full heading weight competed with the
   name instead of introducing it — three items at 15.5:1 stacked in a column read as
   three headings.

   Note the token is NOT --dfx-color-text, despite the name. That is Obsidian #141E2C,
   which is what the workflow name uses and what this glyph has been. The lighter of the
   two body tokens is --dfx-color-text-muted: Pewter #676E7E. The trap recorded in the
   old note still applies in the other direction — `.dfx-workflow__name` overrides the
   heading element role to --dfx-color-text, so neither the icon nor the name is on
   --dfx-color-heading, and the three roles here are easy to confuse by name alone.

   ON CONTRAST, still comfortable. Pewter is 4.72:1 on Signal White — above the 3:1
   WCAG 1.4.11 asks of meaningful non-text, and above the 4.5:1 for body text it does not
   have to meet. These glyphs carry aria-hidden and repeat the label beside them, so they
   are decorative and the 3:1 figure is the generous reading of the requirement rather
   than the binding one. Well clear of the 2.31:1 the original brass sat at.

   The --inverted override further down is unaffected: it sets Signal White outright,
   so it does not matter which light-background value this carries. */
.dfx-workflow__icon {
	display: block;
	margin-bottom: 0.875rem;
	color: var(--dfx-color-text-muted);
	font-size: 1.375rem;
	line-height: 1;
}

/* Salient sets a shared line-height on .fa; reset it so the glyph's own box
   drives the spacing above the name. */
.dfx-workflow__icon .fa {
	line-height: 1;
}

/* Same as the grid title above: no type declared. These render at whatever level
   the element was told to use — h3 or h4 — and were previously forced to 16px
   regardless, which is why an h4 grid item and a 16px h2 section title looked
   identical while claiming different places in the outline. */
.dfx-workflow__name {
	margin: 0 0 0.5rem;
	color: var(--dfx-color-text);
}

/* THE NAME IS A LINK AGAIN — see the note in workflow-grid.php for why it came back.

   Same treatment as `.dfx-feature-group__title a`, which links to the same archive from
   the feature index: no affordance at rest, color on interaction. Eleven underlined
   names would turn a capability summary into a nav list, which is the mistake the
   cell-wide anchor made the first time.

   UNDERLINE ON HOVER AND FOCUS, which the feature archive's version does not carry.
   Color change alone is a weak cue, and no cue at all for anyone who cannot
   distinguish the two — adding the rule on interaction costs nothing at rest.

   SCOPED THROUGH .dfx-workflow-grid FOR SPECIFICITY, (0,2,1). Salient's
   `.wpb_text_column a` is (0,2,0) and would otherwise repaint and underline these if the
   grid ever rendered inside builder content — the trap the old cell-anchor version hit.
   It does not today: the WPBakery workflows element is a tombstone and this is
   template-rendered, verified as not inside a .wpb_text_column on a product page.

   NO `.dfx-workflow--unlinked` CLASS, despite the tombstone below describing one. That
   class existed to drop the affordance from a cell whose term did not resolve; such a
   cell now prints no anchor at all, so the absence IS the difference and there is
   nothing to mark. */
.dfx-workflow-grid .dfx-workflow__name a {
	color: inherit;
	text-decoration: none;
}

.dfx-workflow-grid .dfx-workflow__name a:hover,
.dfx-workflow-grid .dfx-workflow__name a:focus {
	color: var(--dfx-color-brand);
	text-decoration: underline;
}

.dfx-workflow__summary {
	margin: 0;
	color: var(--dfx-color-text-muted);
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-body);
	line-height: var(--dfx-line-height-ui);
	/* Caps the measure so a 90-character summary wraps to two lines rather than
	   running the full width of a wide column. */
	max-width: 22rem;
}

/* NO HOVER OR FOCUS STATES. There is nothing to interact with — the cell is a block,
   not an anchor. The three rules that lived here colored the name on hover, darkened
   the icon to Brass Hover, and drew a focus ring around the cell; all three described
   an affordance the grid no longer has, and `:hover` would have kept firing on the div
   and gone on promising a click. Restore them with the anchor, not before.

   `.dfx-workflow--unlinked` went the same way. It existed to mark a cell whose term
   archive did not resolve, so it could drop the affordance the others had. With no
   affordance anywhere there is nothing to drop, and the class is no longer emitted. */

/* NO DARK-BAND RULES ANY MORE, and this is a tombstone rather than an omission.

   Five rules keyed on `.dfx-workflow-grid--inverted` used to invert the title, the name,
   the hairline, the summary and the icon for a grid sitting on a dark full_width_section.
   NOTHING HAS EMITTED THAT CLASS since the WPBakery workflows element was reduced to a
   tombstone — the element carried the parameter that set it, and the template part that
   replaced it never did. So all five were unreachable, including a fix made to the
   hairline rule while the block was already dead.

   The comment they sat under said the inversion should "key off Salient's own class
   rather than a flag on this element", which is what it should have done and never did:
   the selector was ours throughout.

   TO BRING THIS BACK, key on `.light` — the class Salient puts on a light-text row, and
   the one brand-base.css already uses to switch --dfx-heading-ink to currentColor. One
   thing to know first: the shared section-title rule sets `color: var(--dfx-color-text)`
   outright, so a title inside a .light row does NOT currently invert through that
   mechanism. That declaration has to become currentColor, or the inversion has to state
   the color again, before a dark band reads correctly. Deleting five rules that were
   doing nothing is what makes that fixable rather than apparently already handled. */

/* No --no-icons gap rule any more. It set 2.25rem, which is now the shared base for
   both grids, so the override said nothing. The icon-less variant still works — it just
   inherits the same rhythm as everything else. */

/* THE STEPS DOWN, FOR BOTH GRIDS AND EVERY --cols- VARIANT. Fixing the track counts
   means these have to be stated: auto-fit used to reflow on its own, and four explicit
   columns do not. Left alone they would be about 205px wide here — narrow enough that
   most feature and workflow names wrap, and any item carrying a description reads as a
   column of fragments.

   The --cols- selectors are repeated inside the query because they are 0-2-0 and would
   otherwise beat a 0-1-0 rule on the class alone, holding three or four columns at a
   width where neither fits. The existing 690px block below already had to do this.

   Two rather than three, on the 999px boundary the file already uses. Three would hold
   at 999px and fail at 700px, inside the same query, and a third breakpoint would be one
   more number to keep in step for one intermediate width. */
@media (max-width: 999px) {
	.dfx-workflow-grid__items,
	.dfx-workflow-grid--cols-2 .dfx-workflow-grid__items,
	.dfx-workflow-grid--cols-3 .dfx-workflow-grid__items {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 690px) {
	.dfx-workflow-grid__items,
	.dfx-workflow-grid--cols-2 .dfx-workflow-grid__items,
	.dfx-workflow-grid--cols-3 .dfx-workflow-grid__items {
		grid-template-columns: 1fr;
		gap: 2rem;
	}

	.dfx-workflow-grid__title,
	.dfx-tier-comparison__title,
	.dfx-related__title,
	.dfx-faqs__title,
	.dfx-feature-single__title,
	.dfx-feature-group__title {
		margin-bottom: 1.75rem;
	}
}

/* --- Feature list ----------------------------------------------------------- */
/* template-parts/product/feature-list.php — what a product includes, as a checklist
   grouped under static category labels: Scheduling & Reception, Consumer Solutions,
   Shop, and the rest of dfx_feature_category.

   A CHECKMARK AND A NAME, IN FOUR INDEPENDENT COLUMNS. It was four columns of name +
   one-line description inside Salient accordions, one per category. Both went for the
   same reason: a product carries up to 46 features and this surface is an inventory the
   reader scans to find a capability. Nine of ten categories were closed on arrival, and
   the descriptions made each row three lines tall, so what fitted on screen was about
   six of them. One-line entries in four columns put a whole product in view — the same
   count as the old grid, but each column is a list read downward rather than a row of
   cells.

   IT NO LONGER SHARES THE WORKFLOW GRID'S MECHANICS, which it was built on — same
   tracks, same gap, same 22rem description cap, on the argument that a page carrying
   both should read as one object. That held while both were grids of names with
   summaries. This is a tick list now, so its rules stand alone here, all of them,
   rather than half-riding a shared rule at the top of the file. */
.dfx-feature-list {
	margin: 0 0 3rem;
}

/* THE GROUP SPACING IS BACK, AND SO ARE THE GROUPS. They were <div>s with 3rem between
   them, then Salient toggles that sat flush and separated themselves with a bottom rule,
   and now they are <div>s again — a label over its own grid.

   2.5rem, NOT the 3rem the section carries below it. The gap between a category and the
   next has to read as smaller than the gap between this whole section and whatever
   follows, or the last category looks like it belongs to the next band. */
.dfx-feature-list__group + .dfx-feature-list__group {
	margin-top: 2.5rem;
}

/* THE CATEGORY LABEL. `.dfx-h6` carries the size, the uppercase, the tracking and the muted
   ink — that is the LABEL step in brand-base.css, and the same treatment
   `.dfx-product-group__title` takes over the product archive's family headings. Only the
   spacing is local.

   1rem, TIGHTER THAN THE 1.25rem A LABEL OVER CARDS TAKES. What sits under this one is a
   column flow of one-line entries 0.75em apart, so a label 20px clear of it would float
   further from the entries it names than they sit from each other.

   NO font-family, AND THAT IS A MEASUREMENT RATHER THAN A PREFERENCE. `.dfx-h6` is the
   label role and the role is defined against --dfx-font-body, so this rule was written as
   `font-family: var(--dfx-font-body)` — the same declaration `.dfx-product-group__title`
   carries with a note calling it the one property that is really local there.

   IT LOSES, AND SO DOES THAT ONE. Salient's css/fonts.php emits the h3 family with
   `!important` from Theme Options, so this label renders in Poppins whatever selector is
   written here: probed on a product page at 0-1-0, 0-2-0 and 0-4-3, all Poppins, and only
   `!important` flipped it to Inter. So the declaration came out rather than being escalated,
   because every OTHER section label on the site — the archive's family headings, the feature
   grid's — is losing the identical fight and rendering in Poppins. One label in Inter would
   be the odd one out, and `!important` here would have to be repeated on all of them.

   The rest of the label treatment is unaffected: uppercase, 0.14em, weight 600 and
   --dfx-label-ink all reach it, because brand-base's h6 block is escalated to clear
   Salient's generated file for exactly this reason. Only the family carries !important.

   `.row .col` IS NOT ESCALATED AGAINST HERE, unlike `.dfx-product-group__title`, and the
   difference is worth knowing before this moves: the product page renders its bands outside
   `.container-wrap` with no .row or .col ancestor, so Salient's `.row .col h3` at 0-2-1 does
   not reach — verified on /products/scheduling-package. Drop this section inside builder
   content, which the Feature List element does, and that rule takes the color and the
   letter-spacing. If a label ever renders as full-strength heading ink, that is why; the fix
   is the doubled selector used at `.row .col .dfx-product-group__title`. */
.dfx-feature-list__label {
	margin: 0 0 1rem;
}

/* `.dfx-feature-list--flat` HAS NO RULE HERE, AND THAT IS THE FINISHED STATE. The Feature
   List element's group labels can be turned off, and that branch renders a single <ul>
   carrying every row instead of one labelled grid per category — so there is no group
   wrapper to space and nothing this modifier has to undo. The class rides in the markup as a hook for the
   element's CSS box; see feature-list.php, which explains why the markup switches shape
   rather than the spacing collapsing. Recorded because an unstyled modifier otherwise looks
   like a rule somebody forgot to write. */

/* ---------------------------------------------------------------------------
   FEATURE GRID — the same records, in columns rather than grouped by inclusion

   Four declarations, because the entries themselves are `.dfx-feature-index--fixed`
   further down and this only has to space the sections around them. The list above
   and this share their outer margin so a page carrying one of each steps evenly.

   THE SECTION GAP IS THE GROUP GAP, not a new number. Both are "one bucket of
   features, then the next", and two spacings for one relationship is one to get
   wrong later. */
.dfx-feature-grid {
	margin: 0 0 3rem;
}

.dfx-feature-grid__section {
	margin-bottom: 3rem;
}

.dfx-feature-grid__section:last-child {
	margin-bottom: 0;
}

/* Tighter than the list's title spacing: a label over a row of cards sits directly
   on the grid's own gap, whereas the list's titles sit over flowing text. The label
   is `.dfx-h6`, so its size and color come from that utility — see the
   `.dfx-product-group__title` note for why the LABEL step is the right one over
   items already set at --dfx-size-h5. */
.dfx-feature-grid__label {
	margin: 0 0 1.25rem;
}

/* THE COLUMNS: four equal tracks, each holding ONE COMPLETE <ul>. The lists are split in
   PHP — see feature-list.php for why CSS could not do it — so a column is a real list that
   reads top to bottom, and an entry that wraps lengthens its own column and nothing else.

   ONE GRID ROW, WHICH IS THE WHOLE REASON A GRID IS SAFE HERE. The row coupling that made
   `display: grid` wrong for the ENTRIES cannot bite a single row of four lists: there is no
   second row for a tall column to push down. `align-items: start` keeps a short list at the
   top of its track instead of stretching to the tallest.

   minmax( 0, 1fr ) so a long unbroken name wraps inside its track rather than widening it
   past its quarter of the measure.

   FOUR TRACKS EVEN WHEN THERE ARE TWO LISTS. Column WIDTH has to be the same on every
   category, or a four-feature category would draw its column at full width and a
   twelve-feature one at a quarter. Empty tracks on the right are correct.

   FOUR RATHER THAN FIVE, by request, and it buys measure: at the 1141px content width a
   quarter track is 305px against five tracks' 243px, which is two lines saved on names
   like "Torque Specs (powered by Snap-on Repair information)". The chunk size absorbs the
   change — see the split in feature-list.php, where the divisor is this same count. */
.dfx-feature-list__columns {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	column-gap: 2rem;
	align-items: start;
}

/* Three tracks on a tablet, two on a phone, at the file's own 999/690 boundaries. A set
   split into four lists then wraps onto a second grid row, which is why this needs a row
   gap: 1.5rem is wider than the 0.75em between entries, so a wrapped column reads as the
   next column rather than as more of the one above it.

   The gutter comes down with the count: 2rem between two columns on a 320px measure is a
   tenth of it, and every 32px off the gutter is 16px back into each name. */
@media (max-width: 999px) {
	.dfx-feature-list__columns {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		row-gap: 1.5rem;
	}
}

@media (max-width: 690px) {
	.dfx-feature-list__columns {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: 1.25rem;
	}
}

.dfx-feature-list__items {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* THE ENTRY: a checkmark, then the name, as a two-column grid inside its column so that a
   name wrapping to two lines stays clear of the tick instead of running back under it.
   `align-items: start` keeps the tick on the first line.

   THE BOTTOM MARGIN IS THE SPACE BETWEEN ENTRIES. It sits here rather than as a `gap` on
   the list because each list is a plain block flow now; the last entry's margin is absorbed
   by the column's own end.

   The list-style reset has to be on the `li`: Salient's `ul li` rule matches it directly
   and beats `list-style: none` inherited from the parent. */
.dfx-feature-list .dfx-feature {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	column-gap: 0.5rem;
	align-items: start;
	margin: 0 0 0.75em;
	padding: 0;
	list-style: none;
}

/* THE CHECKMARK, and this selector used to be `content: none` — it existed only to clear
   the bullet Salient's blog skins add. Now it draws the tick, which is also what keeps
   that bullet from coming back.

   U+2713 AS AN ESCAPE, NOT A FONT AWESOME GLYPH, which is the choice `.dfx-integration-list`
   made and the reasoning is the same: Salient ships FA 4.7 and the workflow grid uses its
   classes, but pulling an icon font into a CSS `content` value makes this list silently
   dependent on a font enqueued for other reasons. The tier ladder and the comparison table
   use `fa fa-check` because their ticks are in the MARKUP, where an editor can see them.

   COLOR FOLLOWS --dfx-color-text, matching the ticks in the comparison table and the
   integrations wall so a tick means one thing everywhere. Not brass — see the workflow
   icon's note: an accent reads as decoration, and a tick is meaning.

   NO ARIA CONSIDERATIONS BECAUSE IT IS A PSEUDO-ELEMENT, which is the point of putting it
   here rather than in the markup: the row's text is its content, and a per-row text
   equivalent would have a screen reader read "check" forty-six times. */
.dfx-feature-list .dfx-feature::before {
	content: "\2713";
	grid-column: 1;
	grid-row: 1;
	color: var(--dfx-color-text);
	font-size: 0.875em;
	line-height: var(--dfx-line-height-ui);
}

/* THE NAME IS A SPAN, NOT A HEADING, so it cannot borrow font and weight from the
   heading rules the way .dfx-workflow__name does — that one is a real h3/h4 wearing
   `.dfx-h5` for size only. Stating all three here reaches the same rendered result.

   BODY, NOT THE HEADING SCALE, AND THAT IS THE CHANGE. This was --dfx-size-h6 in
   --dfx-font-heading at --dfx-weight-heading — a title over a description. There is no
   description now: the row IS the name, so it is set as a list entry in the body face at
   the small body size, which is what `.dfx-integration-list` uses for the same job. At
   heading weight, four columns of 600 read as four columns of headings.

   grid-column: 2 pins it beside the tick; see the row rule for why the note stacks under
   it rather than beside it. */
.dfx-feature__name {
	grid-column: 2;
	margin: 0;
	color: var(--dfx-color-text);
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-body);
	line-height: var(--dfx-line-height-ui);
}

/* `.dfx-feature__desc` HAS NO RULE ANY MORE, and the class is no longer emitted here:
   feature-list-item.php stopped printing the feature's short description. It was
   `.dfx-workflow__summary` verbatim, 22rem cap included. Nothing else uses the class — the
   feature CARDS carry their copy as `.dfx-feature-index__desc` — so the rule went rather
   than being left as a dead selector. dfx_get_short_description() is untouched. */

/* The conditional note — "if applicable" — sits between the name and the
   description and has to read as neither. Same size as the description, italic and
   a step lighter, so it registers as a qualifier on the name above it rather than
   as the copy below it.

   THE CLASS IS SHARED WITH FOUR OTHER SURFACES — the feature cards, the feature single and
   two taxonomy templates, all as `.dfx-feature__note--editor`, which carries this base
   class for exactly this block. So the box model stays as it was and the feature list's own
   adjustment is scoped below rather than made here; changing these two lines moves an
   editor note on four templates that never asked for it. */
.dfx-feature__note {
	display: block;
	margin-bottom: 0.25rem;
	color: var(--dfx-steel-gray);
	font-size: var(--dfx-size-body-sm);
	font-style: italic;
	line-height: var(--dfx-line-height-ui);
}

/* NO FEATURE-LIST RULE FOR THE NOTE ANY MORE. It had one for a day: `grid-column: 2` and a
   top margin, to stack the italic note under the name inside the entry. The note is a
   numbered footnote now — marker beside the name, text once under the list — so the entry
   has two children again and nothing to place. The block above still serves the four
   templates that print this class as an editor note. */

/* No `.dfx-feature__note--editor` rule here. It carries the base class too, so it
   picks up the block layout and spacing above, and the editor-note rule further
   down already resets `font-style` to normal and wins on source order at equal
   specificity — restating it here would be one more place to keep in step. */

/* EDITOR-ONLY NOTES on feature rows — dfx_get_feature_editor_note().
   Shown only to users who can edit the feature, explaining why a standalone
   feature is not linked (usually: still a draft).

   Saffron, the warning role, rather than the muted gray the neighbouring
   conditional notes use. These two notes sit inches apart and mean opposite
   things: a conditional note is published copy a visitor is meant to read, this
   is a message to one person about unfinished work. Same color for both and the
   editor stops noticing either. */
.dfx-tier-table__note--editor,
.dfx-feature__note--editor,
.dfx-related__note--editor {
	color: var(--dfx-saffron);
	font-style: normal;
	font-weight: var(--dfx-weight-emphasis);
}

/* The related-products note stands where a whole section would have been, rather
   than beside a row like the other two, so it needs the separation from the
   content above that the absent section was providing. */
.dfx-related__note--editor {
	margin-top: 3rem;
}

/* ============================================================================
   RELATED PRODUCTS
   ============================================================================
   The cross-sell module at the foot of a product page —
   template-parts/product/related.php, rendered by single-dfx_product.php.

   The heading is deliberately NOT styled here. It is declared alongside
   .dfx-workflow-grid__title and .dfx-tier-comparison__title above, because all
   three are the same thing: a section label with a hairline under it, on a page
   that may show two of them one after the other. Restating the values here would
   let them drift, and the drift shows up as two nearly-identical labels with
   slightly different spacing.

   THE GRID RULES BELOW ALSO LAND ON THE PRODUCT ARCHIVE, which uses the same
   .dfx-grid--products class and has never had them — components.css says as much
   further up. That is a deliberate spillover rather than an accident of the
   selector: without it this module renders as a single column of full-width cards,
   which reads as broken, and the archive gains the identical fix for free.

   The card itself is no longer bare. This note used to record the border, padding
   scale and CTA treatment as outstanding; they have since landed in the Product card
   surface section below. Layout lives here, appearance lives there. */
.dfx-grid {
	/* The gap is a property because the track function below has to do arithmetic with
	   it. Two places holding 2rem separately is how a grid ends up one gutter wider
	   than the space it measured itself against. */
	--dfx-grid-gap: 2rem;
	display: grid;
	gap: var(--dfx-grid-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* THREE ACROSS AT FULL WIDTH, STEPPING DOWN ON THE GRID'S OWN WIDTH — not the
   viewport's, and that distinction is the whole of this rule.

   THE BUG IT FIXES: a Related Products band dropped into a one-third WPBakery column on
   /packages measured 382px and still cut three tracks out of it, so cards rendered
   105px wide — titles spilling past the fill, "Book a demo" broken over three lines.
   Nothing was wrong with the card. The column count was stated, and the only things
   that could lower it were the two viewport media queries, which at a 1678px viewport
   are both false however narrow the column is. A page's layout is not its viewport, and
   any element an editor can drop into a column has to size itself on the space it was
   handed.

   HOW IT WORKS. The min of the minmax() is `max( floor, ideal share )`:

     ideal share = ( 100% - (n - 1) * gap ) / n

   which is exactly what one of n tracks would measure in this grid. While the grid is
   wide enough that the share clears the floor, the share wins and auto-fill fits
   precisely n tracks — the identity ( W + gap ) / ( share + gap ) = n makes that exact
   rather than approximate, and it holds at the boundary. Once the grid narrows far
   enough that the share drops below the floor, the floor wins, auto-fill fits however
   many 17rem tracks the space allows, and 1fr shares out the remainder. Below one
   floor's worth the cards stack, which is the ask.

   17rem — 272px — IS THE OLD auto-fit FLOOR, back in service. It is where a product
   title and its built-for line start wrapping badly; three tracks at 999px viewport
   landed each card around 290px, which is the same measurement approached from the
   other side.

   auto-fill, NOT auto-fit, AND THAT IS THE PART THAT LOOKS LIKE THE MISTAKE THIS RULE
   ALREADY MADE ONCE. This grid was auto-fit with a 17rem floor, and it was replaced by
   a fixed count because auto-fit COLLAPSES EMPTY TRACKS: the 1fr maximum then stretched
   what was left, so a family holding two products rendered two half-width cards
   directly above a family holding three at a third each. Card width became a function
   of how many siblings a product happened to have. auto-fill keeps the empty track, so
   a two-product family in a three-track grid leaves the third column empty — which is
   the correct appearance, not a gap to be designed away — and a card is the same size
   everywhere. Verified in the browser at 1265px: one, two and three cards all measure
   400px. Do not "simplify" this to auto-fit.

   minmax( 0, ... ) is gone because the min is no longer 0, but the hazard it guarded is
   still handled: a bare 1fr floors at min-content, so one long product title could push
   the row out of the container. A stated floor of 17rem is a definite min, and
   .dfx-card__title carries an overflow-wrap guard for the word that is longer than the
   card.

   THE COUNT IS STILL A CUSTOM PROPERTY, and it now means "at most n", which is the more
   useful reading of a builder setting. Three is the answer everywhere nothing sets it —
   the /products hub, and every Related products band that does not ask. The Related
   Products WPBakery element writes --dfx-grid-cols inline on the grid, clamped to 2–4
   in template-parts/product/related.php; single-dfx_feature.php writes 2. An INLINE
   property is why the steps could never be expressed as overrides: an inline
   declaration beats any rule in this file, so a media or container query setting the
   property is simply ignored. Putting the whole ladder inside one track function is
   what lets a caller's ceiling and the space available both be respected.

   NO CONTAINER QUERIES, deliberately, and this was written both ways. @container needs a
   containment context declared on an ancestor, which meant `container-type: inline-size`
   on five different owned wrappers — .dfx-related, .dfx-feature-single__products,
   .dfx-workflow-page__products, .dfx-family-page__products, .dfx-product-family — plus
   the ungrouped tail in dfx_render_product_list(), which has no wrapper at all and would
   have silently fallen back to measuring the viewport. A percentage in a track size
   already resolves against the grid's own content box, so the measurement this needs is
   free and lands on every caller including ones not written yet. It also spares five
   sections `contain: layout`, which changes the containing block for absolutely
   positioned descendants inside Salient rows. */
.dfx-grid--products {
	--dfx-card-min: 17rem;
	grid-template-columns: repeat(
		auto-fill,
		minmax(
			max(
				var(--dfx-card-min),
				calc(
					(100% - (var(--dfx-grid-cols, 3) - 1) * var(--dfx-grid-gap))
						/ var(--dfx-grid-cols, 3)
				)
			),
			1fr
		)
	);
}

/* --- Product card surface ---------------------------------------------------- */
/* The card gets a surface, a hairline, a corner and a shadow. Style direction is
   Socket UI's card component; the MARKUP is unchanged — still the article and the one
   __body wrapper that were already here, still Salient's grid around them. Nothing was
   restructured into Socket's header/body/footer parts, because our card carries four
   things in one flow and splitting it would have meant new elements to hold padding
   that a single container already holds.

   WHAT WAS TAKEN: pure white above the page's Signal White, a 1px hairline, an 8px
   corner, the two-layer shadow, and a shadow-only hover. That is the visual language.

   WHAT WAS NOT: the type scale. Socket sets its card title at 18px/600 and its subtitle
   at 14px; this card keeps .dfx-h5 and the brand's own sizes, because the pairing table
   in brand-base.css is the single place sizes are decided and a component copying
   another system's steps is how a scale stops being one. The one type change is the
   built-for line moving to the muted token, which is Socket's muted-subtitle idea
   expressed in this palette.

   .dfx-h5 IS NOW 18px TOO, ARRIVED AT INDEPENDENTLY, and that coincidence is worth a
   line only so nobody reads it as Socket's number having been copied after all. The
   ladder was re-anchored to get h5 off body size; 18px is where a 1.25 ratio lands, not
   where Socket is. The distinction still matters — if Socket moves, this does not.

   The palettes turned out to agree: Socket's card title resolves to rgb(66, 71, 82),
   which is #424752 — this theme's --dfx-color-text exactly.

   :focus-within, NOT :focus-visible. Socket's card is a focusable component and can
   style its own focus; ours is an <article> with no tabindex, so :focus-visible would
   never fire. Keyboard focus lands on the title link or the Learn more link INSIDE it,
   and lifting the card in response is the honest translation — it also means the lift
   is not mouse-only.

   TRANSITION ON box-shadow ONLY, matching Socket's 120ms. No transform: a card that
   moves on hover shifts the text under the pointer, and in a nine-up grid that is a
   page that twitches. */
.dfx-card--product {
	display: flex;
	flex-direction: column;
	/* DARK, matching the homepage tiles. Those are rgba(0, 0, 0, .3) washed over an
	   already-dark section, which composites to roughly this — but a translucent fill
	   cannot travel to a Signal White band, where it would read as a gray veil rather
	   than a card. Solid Obsidian is the same result by the only means available here. */
	background: var(--dfx-color-surface-inverse);
	border-radius: var(--dfx-radius-raised);
	/* NO BORDER. The 1px hairline was doing the separating when the card was white on
	   Signal White; a dark fill on a light page separates itself, and a light-gray ring
	   around a dark tile reads as a seam. The homepage tiles carry no border either. */
	box-shadow: var(--dfx-shadow-raised);
	transition: box-shadow 120ms ease;
}

.dfx-card--product:hover,
.dfx-card--product:focus-within {
	box-shadow: var(--dfx-shadow-raised-hover);
}

/* --- Card internal rhythm ---------------------------------------------------- */
/* ONE GAP INSTEAD OF FOUR DEFAULT MARGINS. Nothing spaced the inside of a card: the
   title, the built-for line, the tier list and the Learn more link each arrived with
   whatever margin its element or Salient's content styles happened to give it — a
   heading's bottom margin against a paragraph's top margin, collapsing in some pairs
   and stacking in others. The result was four different gaps in a four-element stack,
   which is what "the spacing is off" was describing.

   A flex column with a single gap makes every gap the same by construction rather than
   by four values agreeing. The margin reset is what makes it work: `gap` adds to
   margins rather than replacing them, so without zeroing them the gap would be added on
   top of the very inconsistency it is meant to replace.

   `> *` rather than a list of the class names. The original reason was that the Learn
   more link was a Salient-built element among our own children, so naming ours would
   have left out the one whose spacing we did not control. That element now sits inside
   .dfx-card__footer, so every direct child IS ours — but the wildcard stays, because it
   means a fifth element added to the card inherits the rhythm instead of reintroducing
   the bug. The footer overrides the padding half at 0-2-0.

   PADDING IS 1rem, Socket's 16px, on one container. Socket splits it across three parts
   — header 8/16, body 16, footer 8/16/16 — which only matters when those parts have
   their own backgrounds or dividers. Ours do not, so the same measurement lands as one
   inset and the flex gap does the internal spacing. */
.dfx-card__body {
	display: flex;
	flex-direction: column;
	gap: 0.625rem;
	/* Fills the article, so a row of cards is the same height and the link below sits on
	   one line across the grid. The grid already stretches the article itself. */
	flex: 1 1 auto;
	/* 2rem, up from 1rem. The homepage tiles use 35px in a column of much the same width
	   as a card here; 2rem is 32px, the nearest round step in this file's scale, and the
	   roominess is a large part of what the reference reads as. THE FOOTER'S NEGATIVE
	   MARGIN TRACKS THIS — change one and the divider stops reaching the card edge. */
	padding: 2rem;
}

/* PADDING AS WELL AS MARGIN, and leaving padding out was a real bug rather than an
   omission. Salient ships `p { padding-bottom: var(--nectar-paragraph-bottom-spacing,
   1.5em) }` — padding, not margin, on a bare `p` at 0-0-1 — so the built-for paragraph
   kept 24px of padding under its text while its margin read as 0.

   The symptom was spacing that measured identical and looked wrong: every box gap in
   the card was exactly 10px, but the visible distance above "Choose from" was 39.6px on
   a card with an audience line and 18px on one without. The paragraph's BOX was 75px
   tall around 46px of text. Anything reasoning from the gap value alone would have
   concluded the spacing was already consistent. */
.dfx-card__body > * {
	margin: 0;
	padding: 0;
}

/* THE FOOTER: pushed to the bottom, and divided from the content above it.

   ON A WRAPPER RATHER THAN ON THE LINK, which changed when the CTA gained a second form.
   This used to target `.nectar-cta` — the Learn more link itself — and that cannot cover
   the demo button, because nectar_btn puts el_class straight onto the <a>: there is no
   wrapper of its own. The padding below would have overwritten the button's own and
   flattened it. A footer element we own takes the padding instead, and the button stops
   being a direct child of __body, so the `> *` reset does not reach it either.

   `margin-top: auto` is what pins it down, and the card's border is what made that
   necessary — an unequal stack merely ended at different heights before, but inside a
   box one CTA floating mid-card beside another at the foot reads as a mistake. auto
   absorbs whatever slack the tallest card in the row creates.

   THE RULE RUNS EDGE TO EDGE, via a negative inline margin canceled by matching
   padding. Without it the line would stop 1rem short on both sides, because the inset is
   on __body rather than on the footer. That is the one place this deviates from Socket
   UI, which has no footer divider at all — its header, body and footer are separate
   padded parts, so a border there would span the card for free. Ours is one padded
   container, so spanning has to be asked for.

   The margin shorthand carries both jobs — `auto` on top and -1rem on the sides — so it
   cannot be split and half-forgotten. 0-2-0 beats the `> *` reset whatever the source
   order, which matters because that reset zeroes padding too. */
.dfx-card__body > .dfx-card__footer {
	margin: auto -2rem 0;
	padding: 0.75rem 2rem 0;
	/* Inverted, because the card is now dark. --dfx-color-border-subtle is a light gray
	   and all but vanished against Obsidian — the same failure the retired dark-band
	   rules were written for. */
	border-top: 1px solid rgba(255, 255, 255, 0.14);

	/* A ROW, because the footer now holds two things: Learn more always, and the demo
	   button where the product ships. ONE AT EACH END: space-between puts the link on the
	   card's content edge, in line with the title and copy above it, and pushes the button
	   to the opposite edge. The link is the element every card has, so anchoring it left is
	   what makes the footer line up across a row — with the button leading, a coming-soon
	   card's link sat where an available card's button did. On a footer holding only the
	   link — every coming-soon card, and the tier table's button-only one — space-between
	   collapses to flex-start, so the single-item case is unaffected.

	   align-items: center so the arrow link's text sits on the button's optical middle
	   — the two have different heights and baseline alignment would hang the link off
	   the button's first line of text.

	   flex-wrap, so the pair stacks rather than overflowing if the card is ever narrower
	   than the two of them. At the current 345px they occupy about 210px together, so
	   this is a guard rather than a layout in use. */
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem 1rem;
}

/* --- Card typography on the dark fill ---------------------------------------- */
/* EVERY COLOR IN THE CARD HAD TO MOVE, and the reason is worth stating once: each was
   chosen against a white surface. Pewter at 2.9:1 on Obsidian, Baltic at 2.4:1 — both
   were AA-passing on white and both fail here. Nothing about this set is a preference.

   Measured on Obsidian: Signal White 15.5:1, Soft Stone 10.3:1, Brass 6.78:1. The
   homepage tiles use #CACED4 for body copy, which is Soft Stone to within a rounding
   error, so that is the token rather than a new value.

   THE TITLE NEEDS MORE THAN THIS RULE, and assuming otherwise was a bug caught before
   it shipped. The title is an h3, and brand-base.css paints headings with
   `body h3 { color: var(--dfx-heading-ink) }` at 0-0-2 — which beats a `color` set on
   the article at 0-1-0. Left alone the title rendered Graphite on Obsidian at 1.25:1.
   The fix is in brand-base.css: .dfx-card--product joins .light and .dfx-band in the
   list that flips --dfx-heading-ink to currentColor, so the heading inherits the light
   color set here instead of the light-page default. */
.dfx-card--product {
	color: var(--dfx-signal-white);
}

.dfx-card__built-for,
.dfx-card__tiers {
	color: var(--dfx-soft-stone);
}

/* The caller's context line — see the note in card.php. Carried on the card rather
   than by whatever page passed it, so one page cannot style it differently from the
   next.

   NOT muted like built-for and the tier count around it. Those are supporting detail;
   this one exists because the card would otherwise overstate what the buyer gets, so
   it has to survive a skim. Emphasis weight at the caption size the card's other
   secondary lines use.

   NO `color`, DELIBERATELY, AND THE FIRST VERSION HAD ONE. It set
   var(--dfx-color-text) — Graphite, the LIGHT-PAGE ink — which on this card's Obsidian
   fill is 1.25:1 and rendered the line invisible. Exactly the bug the .dfx-card__title
   comment above records against `body h3`, reached from the other direction: not a
   specificity mistake but a token that assumes the wrong surface.

   Inheriting is the fix rather than swapping in Signal White by name. The card sets
   `color: var(--dfx-signal-white)` on itself and documents the contrast — 15.5:1 on
   Obsidian — so inheritance gets the checked value and cannot fall out of step if that
   ever changes. Same argument brand-base.css makes for letting the title inherit
   instead of overriding it. */
.dfx-card__note {
	margin: 0.5rem 0 0;
	font-size: var(--dfx-size-caption);
	font-weight: var(--dfx-weight-emphasis);
}

/* --- Card CTA button --------------------------------------------------------- */
/* The demo button on an available product's card.

   SETS NO SIZE ANY MORE. The 14px label and 0.5rem/0.875rem padding this rule used to
   carry are now the `small` step of the button scale in brand-base.css, which every
   Salient button on the site reads. The values did not change — they moved, because this
   component turned out to be the only reason `size="small"` meant anything, and the tier
   ladder proved it by getting Salient's raw 12px base the moment it asked for the same
   size outside a card footer.

   The 14px is still the right value for the same reason it was chosen here: `.dfx-card__cta`
   — the Learn more link beside it in the same flex row — is 0.9rem, or 14.4px, so at 14px
   the two labels read as a matched pair and the primary action is not visibly smaller type
   than the secondary one next to it. That argument is recorded in brand-base.css now,
   where the value lives.

   ALSO GONE: an explanation that `size="small"` made the font BIGGER, because the
   generated stylesheet declared `.nectar-button.small { font-size: 1rem }`. No such rule
   is loaded on the site today — verified against every stylesheet in the browser rather
   than by grepping one file, which is how the claim got in. Theme Options either stopped
   emitting it or never did.

   margin-bottom: 0 IS NOT TIDINESS, and is the one thing left here. Salient's base rule
   carries `margin-bottom: 10px` for buttons sitting in a builder row, and
   .dfx-card__body's `> *` reset cannot reach this one — the button lives inside
   .dfx-card__footer, which is the whole point of that wrapper. Left in, it adds 10px of
   dead space between the button and the card's bottom edge, on top of __body's own 1rem. */
.dfx-card__footer .nectar-button.dfx-card__cta-button {
	margin-bottom: 0;
}

/* --- Card tier count --------------------------------------------------------- */
/* "2 options available" on the cards of products that have tiers.

   ONE RULE WHERE THERE WERE FOUR. This was a "Choose from" label over a <ul> of tier
   names, which needed a list reset, a marker reset on the li — Salient's `ul li` inside
   .container matches directly and beats list-style inherited from a parent — and a
   ::before clear. All of that existed to render two words a visitor could not act on:
   "Certification" and "Service Boot Camp" mean nothing until you can see what separates
   them, and the page that shows that is one click away. The card only has to say a
   choice exists.

   Muted body copy, a step down from the built-for line above it. It is metadata about
   the product rather than a description of it, and the two should not read as equals.

   No list markup left, so no marker resets. Worth noting only because removing them
   looks like an oversight until you see the <ul> went with them. */
.dfx-card__tiers {
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-body);
	line-height: var(--dfx-line-height-ui);
}

/* --- Product archive page spacing -------------------------------------------- */
/* GONE, not moved. This padded `body.post-type-archive-dfx_product .container-wrap` to
   7.5rem/5rem because the archive had no header band and fell back to Salient's generic
   `.container-wrap { padding: 40px 0 }`. /products is a Page as of content model 1.11.0,
   so that body class never appears and the page header band supplies its own spacing.

   archive-dfx_feature.php still has the original mismatch and never shared this rule. */

/* --- A product page with no builder content ---------------------------------- */
/* Salient's generic `.container-wrap { padding: 40px 0 }` again, this time on the single.
   Eight of nine products author no post_content, so the wrapper held 80px of nothing
   between the submenu bar and the first derived band. single-dfx_product.php adds the
   class only when post_content is genuinely empty — see the note there on why the raw
   field is the test and not the filtered output.

   PADDING, NOT `display: none` OR A REMOVED ELEMENT. The wrapper is Salient's layout
   context for everything below it; collapsing the space is the whole ask and the least
   that achieves it.

   !important because Salient's rule is `.container-wrap` at 0-1-0 and this is 0-1-0 too
   — a class on the same element cannot outrank it on specificity, and load order between
   parent and child stylesheets is not a thing to rely on. The alternative was a second
   class in the selector, which would have meant inventing one purely to win. */
.container-wrap.dfx-product-content--empty {
	padding-top: 0 !important;
	padding-bottom: 0 !important;
}

/* --- Product list groups ----------------------------------------------------- */
/* inc/wpbakery-product-list.php — Software or Services, then the family beneath it, then
   a card grid. Two heading levels where the page had one, and neither had any CSS at
   all before this, which is why the list read as an undifferentiated stack.

   THE FAMILY TITLE CARRIES THE SECTION HAIRLINE, not the root. It joins the shared
   section-title rule rather than restating it, so "Service Intelligence Platform" gets the same inline
   line as "What it handles" and "Core features" — one motif, declared once.

   The ROOT is the small label above it, sharing the sub-group label rule with
   "Additional features". So Software reads as a kicker over the family name rather
   than as a heading over a subheading.

   THAT IS THE REVERSE OF HOW THIS STARTED. The root had the hairline and the family had
   the label voice, and the two were swapped on purpose — see the note where the margins
   are set for what it costs on the size-against-level axis. If the hairline ever reads
   as belonging at the root again, the swap is four selectors and two size classes.

   Spacing rather than rules separates the groups, matching the product page's bands. */
.dfx-product-group + .dfx-product-group {
	margin-top: 4.5rem;
}

.dfx-product-family + .dfx-product-family {
	margin-top: 2.75rem;
}

/* THE TWO TREATMENTS ARE SWAPPED FROM WHERE THEY STARTED, which is worth stating plainly
   because the class names now read the wrong way round: the FAMILY carries the section
   heading with the hairline, and the ROOT carries the small label. Software and Services
   became a kicker over "Service Intelligence Platform" rather than a heading above it.

   BOTH REMAIN h2 AND h3, so an h2 renders at the h6 step above an h3 at the h4 step —
   16px above 20px today. That inverts size against level, which is the thing the
   pairing table in brand-base.css exists to prevent — it was written after an h4 grid
   item and an h2 at body size were found looking alike.
   Taken deliberately: the visual grouping is the point of the page and the outline still
   nests correctly, so a reader navigating by heading gets Software then Service Intelligence Platform in
   the right order even though the sizes say otherwise. If this ever needs to be honest
   on both axes, the root becomes a <p class="dfx-eyebrow"> and the family becomes the h2
   — which is the pattern the hero already uses above its own h1.

   Type and the hairline come from the shared section-title rule further up; only the
   margin is set here. 0.75rem — 12px — down from 2rem, which brings the cards up under
   the name they belong to. The earlier steps are worth keeping on record: 1.5rem read as
   cramped under the hairline, 2.5rem was what detached the cards in the first place.

   THE `.row .col` PREFIX IS WHY THIS TAKES EFFECT AT ALL, and the note beside
   .dfx-integrations-grid__title--group has the long version. Salient's style.css ships
   `.row .col h3, .row .col h4 { margin-bottom: var(--nectar-heading-bottom-spacing,
   16px) }` at 0-2-1; this is an h3 in a WPBakery column, so a single-class rule at 0-1-0
   never won and every value above — 1.5rem, 2rem, the shared rule's 2.5rem — rendered
   alike. Measured on staging it was 8px: the token is set, so the 16px fallback in that
   declaration never applies either. The doubled selector is 0-3-0. Judge the spacing by
   what the browser
   shows, not by the number here, if this ever comes back with only one selector. */
.dfx-product-family__title,
.row .col .dfx-product-family__title {
	margin: 0 0 0.75rem;
}

/* The root, now the quiet one. Type and color come from the shared label rule, with
   .dfx-product-group__title.

   0.875rem, up from 0.625rem. THIS IS THE ONE WITH A CEILING: it is a kicker, and a
   kicker sitting a full line away from what it labels stops reading as attached to it.
   More air between the groups belongs on the family title above, or on
   `.dfx-product-group + .dfx-product-group`. */
.dfx-product-group__title {
	margin: 0 0 0.875rem;
}

/* A root with loose products AND families shows a grid before the first family
   heading. Without this the grid and that heading collide. */
.dfx-product-group > .dfx-grid + .dfx-product-family {
	margin-top: 2.75rem;
}

@media (max-width: 690px) {
	.dfx-product-group + .dfx-product-group {
		margin-top: 3rem;
	}

	.dfx-product-family + .dfx-product-family,
	.dfx-product-group > .dfx-grid + .dfx-product-family {
		margin-top: 2rem;
	}
}

/* NO OUTER SPACING ON .dfx-related OR .dfx-faqs, AND THAT IS THE RULE RATHER THAN A GAP
   IN IT. Both carried `margin-top: 4rem`. It is gone, along with the two rules that
   existed to undo it, and nothing replaces it: THE ROW OWNS THE GAP.

   WHY, because the deleted code is the argument. Three rules were involved and only one
   of them set the margin:

     1. `margin-top: 4rem` here.
     2. A media-query rule zeroing it inside a partial-width WPBakery column, because a
        side column has nothing above it — it had pushed "Fixed Ops Essentials" 64px
        below the top of the card beside it while both columns started at the same y.
        Reported as "there's padding on the top and it doesn't line up".
     3. `.dfx-product-section > .container > .dfx-related` zeroing it inside a band,
        whose own comment conceded "the two together double the gap".

   Two thirds of that was an element apologising for spacing it should never have owned.
   A WPBakery row already has editor-set top and bottom padding, and a template band
   already has its own — so a component that pushes from the top makes both of those
   lie: set the row to zero and you still get 4rem.

   IT WAS ALSO THE ODD ONE OUT. .dfx-workflow-grid, .dfx-feature-list and
   .dfx-feature-grid all declare `margin: 0 0 3rem` — bottom only, which never fights a
   row's top padding because it only ever affects the gap to its own next sibling. These
   two pushed from the top instead, so the house pattern was already the other way.

   AND THE UNDO WAS FRAGILE, which is the part that would have bitten later. Rule 3 is a
   direct-child chain, `.dfx-product-section > .container > .dfx-related`. The Feature
   List and Workflows elements return their markup inside a `--wrap` div, so that chain
   silently stops matching the moment a component is wrapped, while the margin keeps
   applying.

   WHAT THIS COSTS, so it is not a surprise: two of these dropped into ONE WPBakery
   column now sit flush, because neither pushes and there is no row boundary between
   them. That is the accepted trade — the fix for it is a row per band, or padding on the
   column, both of which the editor can see and set. Checked when this landed: the
   /packages FAQ row and the related bands on product pages take their air from the row
   and the band respectively. */

/* No rule. See above. */

/* The two band labels in .dfx-related's add-ons mode — "Products" over the cards,
   "Features" over the feature cards, and only when both bands are present. Type comes
   from .dfx-h6, which is the label role rather than a size, so nothing is restated.

   THE DOUBLED SELECTOR IS NEEDED: an h2/h3 inside a WPBakery column hits `.row .col h3` at
   0-2-1 with --dfx-heading-ink, beating `.dfx-h6` at 0-1-0 — the trap
   .dfx-product-group__title documents above. --dfx-label-ink, not the flat muted token, so
   the label follows the text down on a dark band. */
.dfx-related__band-title,
.row .col .dfx-related__band-title {
	margin: 0 0 1.25rem;
	color: var(--dfx-label-ink);
}

/* The second band's air, set on whatever follows the grid so it lands on the label when
   there is one and on the list when there is not. 3rem matches the gap between the
   feature-list groups this band is a sibling of in spirit. */
.dfx-related .dfx-grid--products + .dfx-related__band-title,
.dfx-related .dfx-grid--products + .dfx-feature-index {
	margin-top: 3rem;
}

/* THE LAST VIEWPORT RULE LEFT ON THIS GRID, and it survives its sibling because of the
   direction it moves in. The 999px two-column step was deleted when the track function
   above learned to measure the grid: a hard column count in a media query cannot see the
   container, so at a 900px viewport it forced two tracks into a 382px column just as
   confidently as three were forced at 1678px.

   ONE COLUMN ON A PHONE IS A DECISION, NOT A FIT. A 610px content measure divides into
   two 289px cards, which clears the 17rem floor, so the track function would leave them
   side by side and be right to. We want the full measure per card at this size anyway.
   Safe as a media query for the same reason the other one was not: it only ever REDUCES
   the count, so a narrow container on a small screen still ends up stacked. */
@media (max-width: 690px) {
	.dfx-grid--products {
		grid-template-columns: 1fr;
	}

	.dfx-related {
		margin-top: 3rem;
	}

	.dfx-related .dfx-grid--products + .dfx-related__band-title,
	.dfx-related .dfx-grid--products + .dfx-feature-index {
		margin-top: 2.25rem;
	}
}

/* ============================================================================
   PRODUCT SECTIONS — the self-assembling bands
   ============================================================================
   Rendered by single-dfx_product.php below .container-wrap: the feature table or
   flat list, Works with, and Related products. Each spans the viewport; the inner
   .container hands back the page measure, so the table lines up with everything
   above it while its background and top rule run edge to edge.

   NO WIDTH OR BLEED RULES HERE, deliberately. The section is outside .container-wrap,
   so full width is simply what a block element does — there is nothing to trick. That
   is the whole reason the template moves them out rather than styling them in place.

   NO BORDERS ON THESE BANDS. A top rule was tried on all three and then on the
   features band alone, and both were wrong for the same reason: the section headings
   already carry a hairline each, so a band rule sat a few rem above another line and
   read as a boxed region rather than a division. Spacing separates these sections;
   the headings mark them.

   What the bands are for is the full-bleed capability — a background that can run
   edge to edge while the content keeps the page measure. Give one a background and it
   bleeds correctly with no further work; the features band below uses the same
   capability in reverse, dropping the surface so the page's own shows through. */
/* 5rem, UP FROM 2.5rem, BECAUSE THE HAIRLINE CHANGES THE ARITHMETIC. 2.5rem was half
   of an intended 5rem gap on the reasoning that both neighbours contribute to an
   unmarked boundary. A border divides that boundary, so each side now reads on its own
   and 2.5rem read as half the space. Bottom edge, cleared on the last band below. */
.dfx-product-section {
	padding-block: 5rem;
	background: var(--dfx-color-surface);
	border-bottom: 1px solid var(--dfx-color-border-subtle);
}

/* THE FEATURES BAND OPTS OUT, so the page's white runs behind the comparison table.
   #F5F6F7 under a table that draws its own hairlines and tints one column read as a
   slab with a table floating on it; on white the table is the only surface.

   AND UNRULED ON BOTH EDGES, which is the reason for the `:has()`. A band owns only
   its bottom border, so the line above the features band belongs to whichever band
   precedes it — dropping one and not the other left the white bounded by a hairline
   at the top and nothing at the bottom. The surface change is the division here; a
   rule beside it is the boxed-region problem the block above documents.

   `:has()` rather than `--workflows`, because the band order is `Meta::sections()`
   and any band can be absent. Unsupported :has() leaves the top hairline: the
   asymmetry, not a broken layout. */
.dfx-product-section--features,
.dfx-product-section:has(+ .dfx-product-section--features) {
	border-bottom: 0;
}

.dfx-product-section--features {
	background: transparent;
}

/* Padding pinned independently of the base above, because this is clearance over the
   footer rather than a gap shared with a neighbour. Border dropped: there is no next
   band to divide from, and the footer draws its own hairline. :last-of-type is safe
   here — the bands are the only <section> at this level. */
/* THE OVERRIDDEN BAND HEAD — eyebrow, heading, deck. Only ever printed when an editor
   has typed a heading or a sub-heading, so nothing here reaches the nine products
   published against the bands' own h2.

   Its own classes rather than the shared .dfx-product-section__title, deliberately.
   That selector is one of seven in a group that draws a trailing hairline with ::after
   and sits at the h4 label step — both correct for a two-word label and wrong for a
   sentence with an eyebrow over it. Borrowing it would have meant unpicking a rule six
   other templates depend on. */
.dfx-section-head {
	margin: 0 0 2.5rem;
	/* Matches the deck measure on the hero, for the same reason: the column decides the
	   width, this decides the line length. */
	max-width: 46rem;
}

/* NO EYEBROW RULE HERE. The head prints .dfx-eyebrow, which owns the size, weight,
   tracking, ink and the gap below it. This block used to restate all five at different
   values and was the reason this eyebrow sat further from its heading than the ones in
   page content. */

.dfx-section-head__title {
	margin: 0;
}

.dfx-section-head__deck {
	margin: 0.75rem 0 0;
	color: var(--dfx-color-text-muted, #5F656E);
}

.dfx-product-section:last-of-type {
	padding-bottom: 5rem;
	border-bottom: 0;
}


/* The last band carries the footer's own rule beneath it, so it needs no bottom
   border of its own — and `.container-wrap`'s padding-bottom is what separates the
   builder content from the first band. */

/* THE PARTS INSIDE LOSE THEIR OUTER MARGINS. Each was written to sit in a stack inside
   .container, so each carries a bottom margin to hold itself off the next one. Inside a
   band the padding does that, and the two together double the gap.

   SHORTER THAN IT WAS: .dfx-related and .dfx-faqs are no longer listed, because they no
   longer have an outer margin to zero — see the note where their `margin-top: 4rem` used
   to be. The example that comment used to give, ".dfx-related alone was adding 4rem on
   top of the band's own padding", is the reason it was removed at source instead.

   STILL A DIRECT-CHILD CHAIN, and worth knowing that this is its weakness: a component
   wrapped in anything — as the Feature List and Workflows elements wrap theirs — falls
   out of this selector while keeping its margin. The three below are template-rendered
   into `.container` directly, so it holds for them; it is not a pattern to extend to
   anything an element can place.

   Zeroed here rather than in each component, so the components still stand alone if they
   are ever used outside a band. */
.dfx-product-section > .container > .dfx-workflow-grid,
.dfx-product-section > .container > .dfx-tier-comparison,
.dfx-product-section > .container > .dfx-feature-list,
.dfx-product-section .dfx-product__integrations {
	margin-top: 0;
	margin-bottom: 0;
}

/* THE BANDS CARRY ANCHOR IDS, so they need somewhere to land. `#header-outer` is
   `position: fixed` at 72px, and a fragment jump scrolls the target to y=0 — straight
   under the header, with the section title hidden behind it. `scroll-margin-top` is the
   fix rather than a negative-margin or pseudo-element trick: it changes only where the
   scroll stops, not the layout, so nothing shifts for a visitor who never uses the menu.

   9rem CLEARS THE STICKY SUBMENU AS WELL AS THE HEADER — 72px of header, 66px of
   [page_submenu] once it sticks, and the rest as air. Sizing it to the header alone put
   every heading behind the menu bar the reader had just clicked. The bar measured 62px
   at the 14px it inherited and gains a few with the size below, which is the whole
   reason these two numbers travel together.

   Not tied to a --var because neither height is ours to publish: Salient owns the header,
   and the submenu's height comes from its own element CSS. If either is re-sized, this is
   the second thing to change. Salient's init.js does its own offset maths for clicks it
   handles, so this governs direct fragment loads — a shared link landing straight on a
   section — and is the case worth checking on a real page. */
.dfx-product-section {
	scroll-margin-top: 9rem;
}

/* THE SAME OFFSET FOR THE ELEMENTS THAT CARRY AN ANCHOR ID, which until now was the one
   thing a builder-placed anchor could not get. `.dfx-product-section` above is emitted by
   single-dfx_product.php, so a fragment link into a derived band cleared the header and a
   fragment link into an element placed on a Page did not — it landed with the section's
   first heading behind the fixed bar. Same figure, deliberately: it is the same header
   being cleared, and two numbers for one obstruction is one to get wrong when Salient's
   header height changes.

   THESE ARE THE WRAPPERS, NOT THE SECTIONS INSIDE THEM. Each element returns its markup in
   a `--wrap` div that carries the id, so the offset has to sit on the thing the fragment
   actually targets. The tier comparison's toggle mode is the case that proves it — the id
   is on the wrapper there precisely because the panel below it can be closed. */
.dfx-workflows-wrap,
.dfx-feature-list-wrap,
.dfx-tier-comparison-wrap {
	scroll-margin-top: 9rem;
}

/* ============================================================================
   PAGE SUBMENU — Salient's [page_submenu], the in-page menu on product pages
   ============================================================================

   14px — --dfx-size-body-sm, which the token file calls the workhorse for "cards,
   feature lists, nav". Salient sets no font-size on these links at all, so this is also
   what they inherited before anyone touched them.

   THIS WAS 16px AND WENT BACK DOWN, which is a reversal worth recording rather than
   quietly re-editing. The argument for 16px was that 14px is too quiet for the only
   wayfinding on a page five bands long. What made it quiet was mostly the opacity, and
   that half of the fix stays — see below. The bar now carries a title and a button as
   well as links, and at 16px the three of them read as three competing sizes; a step
   down puts the links under the product name instead of level with it.

   THE OPACITY MATTERED AS MUCH AS THE SIZE. Salient rests these links at 0.7 and takes
   them to 1 on hover, which on a white bar reads as disabled rather than available —
   half of "too small" was really "too faint". 0.85 keeps the hover mechanic doing
   something visible without the resting state looking switched off.

   `html body` TO BEAT `body .page-submenu li a`, which is Salient's own selector at
   0-2-2. Ours has to outweigh it rather than rely on load order, because
   nectar-element-page-submenu is enqueued after dfx-components in
   dfx_child_enqueue_styles() and would otherwise win the tie. Same escalation the
   accordion titles use, for the same reason.

   The active item takes weight rather than color: Salient's own `.current-menu-item`
   rule is scoped to `.stuck`, so color alone would appear only once the bar had
   stuck. */
html body .page-submenu li a {
	font-size: var(--dfx-size-body-sm);
	opacity: 0.85;
}

html body .page-submenu li a:hover,
html body .page-submenu li a:focus,
html body .page-submenu .current-menu-item a {
	opacity: 1;
}

html body .page-submenu .current-menu-item a {
	font-weight: var(--dfx-weight-emphasis);
}

/* A hairline under the bar, so it reads as an edge rather than as white bleeding into
   the page — the bar is #fff on a Signal White surface, which is barely a step.

   `--dfx-color-border-subtle`, NOT full-strength Soft Stone. The token file's guidance
   that full strength is "right for a single divider" is written about dividers on a
   surface; this one runs the full width of the viewport under a sticky bar, where the
   same value reads as a drawn line rather than an edge. It also sits at a boundary, so
   it reads against the #fff bar above it as much as against the page below — 1px of
   #E3E5E7 on white is a visible edge, which is the earlier worry about invisibility
   answered.

   On `> div` rather than the class, because that child is `.full-width-content` at
   center alignment and `.full-width-section` at left or right — the border should not
   quietly disappear if the alignment is ever changed. It carries the inline background,
   so the rule lands at the bottom of the color rather than below it. */
.page-submenu > div {
	border-bottom: 1px solid var(--dfx-color-border-subtle);
}

/* The product name. `display: none` here is the sub-1000px case only; the media block
   below turns it on for every scroll position.

   EVERY TYPE PROPERTY IS STATED, because this is an <li> in a nav list and carries no
   pairing class. It used to wear `.dfx-h5` for 18px, which also brought the leading and
   tracking; the bar now runs a step below the heading scale, and the next step down is
   `.dfx-h6` — the uppercase label role, not a size. So the three values `.dfx-h5` was
   supplying are restated here, at 16px rather than 18px.

   Family and weight were always explicit and still have to be. `.dfx-hN` never carries
   font-family — Poppins arrives from the element selectors (`h1`–`h6`, `.wpb_wrapper h5`)
   — so a heading class on a non-heading tag renders at heading size in Inter. Weight the
   same: the scale expects 600 to arrive from the heading the class normally sits on.

   Don't reach for Salient's `[data-inherit-heading-family]` instead — it is inert on
   this site. */
.page-submenu .dfx-submenu-title {
	display: none;
	font-family: var(--dfx-font-heading);
	font-size: var(--dfx-size-body);
	font-weight: var(--dfx-weight-emphasis);
	line-height: var(--dfx-line-height-heading-small);
	letter-spacing: var(--dfx-letter-spacing-heading-small);
	color: inherit;
}

/* Hidden below 1000px, where Salient moves the <ul> into a closed dropdown behind a
   "Menu" button. Both of these live in the list, so neither can sit in the bar there — a
   product name is noise inside a dropdown and a primary action inside one is worse than
   no action. Mobile keeps the hero band's button.

   BOTH BASE RULES COME BEFORE THE MEDIA BLOCK ON PURPOSE. The reveals below are 0-2-0,
   the same as these, so source order is the whole of what makes them win. Moved after and
   the bar loses its title and button at every width. */
.page-submenu .dfx-submenu-cta {
	display: none;
}

/* 2rem BOTH SIDES OF THE TITLE'S RULE, replacing Salient's 25px. 32px is on the spacing
   scale this file uses everywhere and 25px is on nothing — it is the element's own
   default. The padding holds the name off the border and the margin holds the first link
   off it, so both halves have to be stated or the divider sits off-center in its own gap.
   `.page-submenu li` is 0-1-1, so this wins the margin at 0-2-0 without escalation. */
@media (min-width: 1000px) {

	/* SHOWN AT EVERY SCROLL POSITION, not only stuck, which reverses the earlier call.
	   The argument for hiding it was that the h1 sits directly above the bar unstuck, so
	   the name is said twice within 60px. Dave's call that the label is worth the
	   repetition: the bar reads as this product's menu from the first look rather than
	   acquiring a subject on scroll, and nothing shifts position when it pins. */
	.page-submenu .dfx-submenu-title {
		display: inline-block;
		margin-right: 2rem;
		padding-right: 2rem;
		border-right: 1px solid var(--dfx-color-border-subtle);
	}

	/* Title and links left, CTA right. `!important` and 0-3-3 are both needed: Salient
	   sets `.page-submenu ul { display: block !important }` at 0-1-1 inside its own
	   min-width:1000px block, so specificity alone loses to the important and important
	   alone loses on nothing — it takes the pair.

	   NO font-size HERE, and that was an attempt that did not work. Setting it on the
	   <ul> for the links to inherit looked cheaper than fighting a selector, but
	   `html body .page-submenu li a` further up this file already declares the link size
	   explicitly — so the ul value reached the <li>s and stopped. The size lives in that
	   rule; the title and the button state their own. */
	html body .page-submenu[data-alignment="left"] .container > ul {
		display: flex !important;
		align-items: center;
	}

	/* LAID OUT FROM THE START AND EASED IN ON PIN, which is why this is opacity and not
	   display. `display` cannot be transitioned, and the button is the one thing in the
	   bar that should arrive rather than just be there — the hero's own button is still on
	   screen unstuck, so a second one competes with it.

	   Holding the layout while hidden is free here: the button is the only thing at the
	   right end, so reserving its width moves nothing. That is also what lets it fade in
	   place instead of the row reflowing around it mid-transition.

	   `visibility` IS IN THE TRANSITION LIST DELIBERATELY. It keeps the hidden button out
	   of the tab order and off the a11y tree, which opacity alone does not do, and being
	   discrete it flips at the far end of the timing — so the fade OUT stays visible
	   instead of the button vanishing on frame one.

	   `flex` so the li is exactly the button's height with no line box under it — measured
	   46px against a 36px button as a block, which centerd the li and left the button 5px
	   high in the bar. The other 10px was Salient's button margin; see below.

	   0.3s matches Salient's own `.page-submenu.stuck { transition: all 0.3s }`, so the
	   button settles with the bar rather than after it. */
	.page-submenu .dfx-submenu-cta {
		display: flex;
		align-items: center;
		margin-left: auto;
		margin-right: 0;
		opacity: 0;
		visibility: hidden;
		transform: translateY(-0.5rem);
		transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
	}

	.page-submenu.stuck .dfx-submenu-cta {
		opacity: 1;
		visibility: visible;
		transform: none;
	}
}

/* Reduced motion keeps the reveal and drops the easing — the information is that the
   button is there, not that it slid. Same treatment as the integrations grid below. */
@media (prefers-reduced-motion: reduce) {

	.page-submenu .dfx-submenu-cta {
		transition: none;
		transform: none;
	}
}

/* Salient's `body .page-submenu li a` (0-1-3) fades every link to 0.7 and blocks it. The
   button is not a nav link: 0-2-2 wins on the class count and restores its own box.
   Padding is NOT restated — `html body .nectar-button.small:not(.has-icon)` is 0-3-2 and
   already outranks Salient's 20px. */
body .page-submenu .dfx-submenu-cta a {
	display: inline-block;
	opacity: 1;

	/* 13px, a step under the 14px `html body .nectar-button.small` gives it, so the button
	   comes down with the rest of the bar. That rule is also 0-2-2, so this wins on load
	   order alone — components.css declares brand-base as a dependency. Scoped to the bar,
	   so every other small button on the site keeps 14px. */
	font-size: var(--dfx-size-caption);

	/* Salient's base rule gives every button `margin-bottom: 10px` for builder rows. In a
	   67px bar that is 10px of dead space below the button and 5px of apparent misalignment
	   — the same trap .dfx-card__footer documents further up. */
	margin-bottom: 0;
}

/* SALIENT CANNOT MATCH ITS OWN WHITE. Its mobile dropdown borders are keyed to
   `[data-bg-color="#ffffff"]` while the mobile-menu-link borders next to them are keyed
   to `[data-bg-color="#fff"]` — two literals for one color, so no single value we pass
   satisfies both and one set of borders is always white on white. We pass `#fff`, which
   wins the divider, and this restores the row borders it loses. */
@media (max-width: 999px) {

	.page-submenu[data-bg-color="#fff"] ul li a {
		border-top: 1px solid var(--dfx-color-border-subtle);
	}
}

/* Smooth only where the visitor has not asked otherwise. An in-page menu that jumps is
   disorienting on a long product page — the reader loses the sense of having moved — but
   animated scrolling is exactly what prefers-reduced-motion exists to suppress. */
@media (prefers-reduced-motion: no-preference) {

	html {
		scroll-behavior: smooth;
	}
}

/* Works with gets the same hairline heading as every other section title, which it
   did not have before — it was a bare `.dfx-h4`. Declared with the others up in the
   shared rule; this only adds the class to the markup's list. */

/* ============================================================================
   FEATURE PAGES
   ============================================================================
   single-dfx_feature.php and archive-dfx_feature.php. Both existed as nothing
   until recently — features fell through to Salient's single.php and archive.php
   and rendered as blog posts, complete with an author byline and a Categories
   sidebar.

   The band shares .dfx-product-band, which is the point — one component, one set
   of colors and type. It diverges in exactly one respect, below.

   Section headings are not here either — .dfx-feature-single__title and
   .dfx-feature-group__title are declared with the workflow grid and tier table
   titles above, because all four are the same thing: a section label with a
   hairline under it. A feature page can show three in a row. */

/* THE FEATURE BAND DOES NOT NEED THE PRODUCT BAND'S TOP CLEARANCE, and inheriting
   it was a bug. `.dfx-product-band__inner` carries 7.5rem of padding-top for one
   reason, stated in that rule: products always start with a TRANSPARENT navigation,
   so the nav sits over the band and the band has to make room for it.

   Features do not. `dfx_product_transparent_nav_verdict()` is gated on
   `dfx_is_single_product()`, so a feature gets a solid nav and a `#header-space`
   element reserving its height — and then 120px of padding for a nav that is not
   overlapping anything, plus the breadcrumb's own 5rem before the eyebrow. The band
   opened with roughly 200px of empty space.

   Reset to a normal band inset. The bottom padding is inherited untouched, since
   nothing about the foot of the band differs.

   0,2,0, so it also wins over the ≤690px variant of the product rule at 0,1,0 —
   3.5rem is already compact enough for a phone, so the feature band uses one value
   at both breakpoints rather than a second override that would have to be kept in
   step with the product's. */
.dfx-feature-band .dfx-product-band__inner {
	padding-top: 3.5rem;
}

/* The breadcrumb-to-eyebrow gap comes down with it. On a product that 5rem is
   deliberate — the trail and the eyebrow are two different kinds of thing and the
   band is tall enough to afford separating them. In a band a third of the height it
   is most of the band. */
.dfx-feature-band .dfx-breadcrumbs {
	margin-bottom: 2rem;
}

/* Screenshot. The featured image is labeled "Screenshot" on this post type, and
   on a feature page it is the most persuasive element available — so it gets the
   full content measure rather than being inset like a figure in an article. */
.dfx-feature-single__media {
	margin: 0 0 3rem;
}

.dfx-feature-single__media img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 4px;
}

.dfx-feature-single__content {
	margin-bottom: 3.5rem;
}

.dfx-feature-single__products,
.dfx-feature-single__workflows,
.dfx-feature-single .dfx-product__integrations {
	margin-bottom: 3.5rem;
}

/* HOW TO GET IT HAS NO RULES OF ITS OWN ANY MORE, and the whole block that was here
   is gone: `.dfx-included-in` and its `__item`, `__product`, `__level` and
   `__level--add_on`, roughly fifty lines of bordered flex row, link color and chip
   fill. That section now renders `.dfx-grid--products` full of `.dfx-card--product`,
   which are both styled elsewhere in this file, and the inclusion level rides in as
   `.dfx-card__note`.

   The argument for the list is worth keeping, because it was a real one: there are
   rarely more than three products, and the level was the information that mattered,
   so a row pairing name with chip kept that legible. What changed is that the feature
   page lost the band CTA and the closing CTA, so this section became the only place on
   it that can convert — and a name plus a chip cannot. See single-dfx_feature.php.

   LIST MARKERS HAVE TO BE RESET ON THE `li`, NOT THE `ul`. Salient ships
   `ul li { list-style: disc; list-style-position: outside }`, and a declaration
   matching the li directly beats `list-style: none` INHERITED from its parent —
   inheritance loses to any matching rule regardless of specificity. So every list
   below resets on its items as well.

   The workflow grid already learned this; see the note beside
   `.dfx-workflow-grid .dfx-workflow`. */
.dfx-term-list,
.dfx-integration-list,
.dfx-feature-index {
	margin: 0;
	padding: 0;
	list-style: none;
}

.dfx-term-list > li,
.dfx-integration-list > li,
.dfx-feature-index > li {
	list-style: none;
}

/* ADD-ON USED TO BE THE ONE LEVEL WORTH COLORING — saffron on the chip, the same
   caution tone coming-soon uses, on the reasoning that it is the level costing extra
   and the page should not bury that. Worth recording, because the card note replacing
   it is plain body text and makes no such distinction.

   The emphasis did not disappear with the color, it moved: only levels that are NOT
   simply included print a note at all now, so "Available as add-on" is the only thing
   in that slot rather than one chip among three. Being the only card in the grid
   carrying a line is a stronger signal than being the one carrying a warm chip.

   If it ever needs marking again, it is `.dfx-card__note` on that card and the note is
   a sentence rather than a chip, so it wants weight or ink — not a fill. Do not
   reintroduce a colored pill: components.css reserves a colored fill for
   availability, and the archive's cards would then have two chip vocabularies. */

/* PART OF. Chips, wrapping inline rather than stacking: these are three or four
   short workflow names, and a stacked list gives each one a full row of empty space
   beside it.

   THIS USED TO BE DECLARED TOGETHER WITH .dfx-integration-list, "so they cannot
   drift". They have now deliberately drifted — Works with is a checklist below —
   so the shared declaration is gone rather than left as a selector list with one
   name in it. The two lists answer different questions and no longer look alike. */
.dfx-term-list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 0.75rem;
}

.dfx-term-list a {
	display: inline-block;
	padding: 0.375rem 0.75rem;
	border: 1px solid var(--dfx-color-border);
	border-radius: 2px;
	color: var(--dfx-color-brand);
	font-size: var(--dfx-size-body-sm);
	text-decoration: none;
	transition: border-color 0.15s ease, color 0.15s ease;
}

.dfx-term-list a:hover,
.dfx-term-list a:focus {
	border-color: var(--dfx-color-brand);
	color: var(--dfx-color-text);
}

/* THE INTEGRATION TYPE PILLS ARE RAISED AND THE OTHER THREE TERM LISTS ARE NOT.
   These sit inside a Signal White panel, where a bordered outline on a tint reads as
   a disabled field and a white chip reads as a control. The family and feature lists
   stay flat: they are on the white page, with no tint for a white fill to lift off.

   Same specificity as the base rules above, 0-1-1, so this wins on source order and
   has to stay below them. */
.dfx-term-list--integration-types {
	/* Up from 0.5rem/0.75rem. --dfx-shadow-raised throws 8px of blur, so at the old
	   vertical gap two stacked rows dropped shadow onto each other. */
	gap: 0.75rem;
}

.dfx-term-list--integration-types a {
	/* Sides widened for the reason .dfx-badge widened its own: the curve eats the
	   space beside the first and last letter, so padding tuned to a 2px corner reads
	   as cramped once the ends are round. */
	padding: 0.5rem 1rem;
	background: var(--dfx-color-surface-raised);
	/* Subtle, not --dfx-color-border. Soft Stone under a shadow reads muddy — the two
	   are drawing the same edge twice. */
	border-color: var(--dfx-color-border-subtle);
	/* 999px, following .dfx-badge rather than the theme's 2px default; the argument is
	   recorded there, including why not 50%. */
	border-radius: 999px;
	box-shadow: var(--dfx-shadow-raised);
	transition: border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

/* THE LIFT IS THE HOVER. The inherited border-color and color changes still apply and
   still carry the state; this adds the shadow step the product card uses, which is
   what the eye actually catches on a fill this close to its surface. */
.dfx-term-list--integration-types a:hover,
.dfx-term-list--integration-types a:focus {
	box-shadow: var(--dfx-shadow-raised-hover);
}

/* WORKS WITH. A tick list in as many columns as fit at a width no name wraps in,
   capped at eight.

   THIS USED TO BE COLUMN-MAJOR — grid-auto-flow: column over an explicit six-row
   track, on the rule that a column holds six items. That fixes the ROW count and
   lets the COLUMN count run: Service Intelligence Platform carries 64 integrations, so it drew eleven
   columns of 82px inside a 1141px measure and wrapped nearly every name. Six per
   column was only ever right while the set was thirty.

   So the cap moves to the axis that was overflowing, and auto-fill counts the
   columns rather than the stylesheet asserting them.

   THE 10.5rem FLOOR IS MEASURED, NOT ROUND. "Meadowland Systems" is the longest name
   at 146px in --dfx-size-body-sm, plus the tick and its gap. Narrower than this and
   an entry goes to two lines, which in a tick list reads as two entries.

   The max() is the ceiling. Below a 1512px measure the floor is the larger value and
   decides the count; above it the eighth-share wins and pins the count at eight.
   Past eight the names are still legible but the block stops scanning as a list.

   Reading order changes with this, and that is the trade: the DOM stays alphabetical
   from dfx_get_integrations(), so it now reads across rows rather than down columns. */
.dfx-integration-list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(max(10.5rem, (100% - 7 * 1.5rem) / 8), 1fr));
	gap: 0.5rem 1.5rem;
}

.dfx-integration-list > li {
	display: flex;
	align-items: baseline;
	gap: 0.5rem;
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-ui);
}

/* The tick, as a Unicode escape rather than a Font Awesome glyph. Salient ships FA
   4.2 and the workflow grid uses its classes, but that is markup an editor chose;
   pulling the icon font into a CSS `content` value makes this list silently
   dependent on a font that is enqueued for other reasons. U+2713 needs nothing. The
   `\2713` escape form matches the pagination chevron at the top of this file.

   align-items: baseline above rather than center, so the tick sits on the same line
   as the first word if a name does wrap — the track floor is sized so none should,
   but centerd it would float to the middle of the block the moment one did.

   Color follows --dfx-color-text, the same correction the workflow icon took when
   brass read as decoration rather than meaning. A tick is not an accent. */
.dfx-integration-list > li::before {
	content: "\2713";
	flex: none;
	color: var(--dfx-color-text);
	font-size: 0.875em;
	line-height: inherit;
}

/* No anchor rules here on purpose. These are plain names until
   single-dfx_integration.php exists — see the note in single-dfx_product.php — and
   the link styling came off with the markup rather than being left as a dead
   selector, the same way the workflow grid's cell anchor was handled. */

/* NO ≤999px BRANCH ANY MORE, and its absence is the point. It existed only to undo
   the column-major grid above — a fifth of a 780px measure is 156px, which wrapped
   "Reynolds & Reynolds" in every column — by switching to the auto-fill it now uses
   at every width. One rule where there were two, so the two cannot drift.

   Tablet lands on four or five columns, tracks around 180px, which is what the old
   12rem floor was reaching for.

   One column on a phone. Two fit at 420px, but a tick list is read down rather than
   scanned across; the floor would give at most two here anyway, and below a 360px
   measure auto-fill reaches one on its own. Stated rather than left to arithmetic. */
@media (max-width: 690px) {
	.dfx-integration-list {
		grid-template-columns: 1fr;
	}
}

/* THE CLOSING CTA IS GONE — `.dfx-feature-single__cta` and its `__cta-link`, a
   hairline-topped band holding a filled CTA-orange link. It was a link rather than a
   button for the same reason the card's is: dfx_get_cta() decided the words, and on a
   coming-soon feature they are "Get notified", which a heavy primary button oversells.

   Removed with the band's Book a demo, because a feature is not a purchasable thing
   and every route to owning one runs through a product. The offer now sits on the
   product cards in "How to get it", each gated on its own availability.
   single-dfx_feature.php carries the full reasoning.

   NOTHING ELSE READ THESE RULES, but the tokens are not orphaned: --dfx-color-cta and
   --dfx-color-cta-hover are still used by Salient's buttons and the hero. */

/* --- Feature archive -------------------------------------------------------- */
/* Grouped by workflow, in service drive order. The group heading links to the
   workflow archive, so each one is a route into the aggregation pages rather than
   a dead label. */
/* 6rem, AND THE OLD 4rem WAS NOT MERELY TIGHT — IT TIED. The gap below a group was
   64px and the gap INSIDE one, from the group's description down to its first row, is
   also 64px. So the distance separating two sections was exactly a distance within one,
   and nothing in the spacing said where a section ended. That is the same fault this
   archive had twice over at smaller scales this week, one level up.

   The ladder now reads 96 / 64 / 40: section boundary, then group intro, then row gap.
   Each step of the hierarchy is visibly larger than the one nested inside it, which is
   the only thing that makes grouping legible without a rule or a surface to draw it.

   The ≤690px override stays at 3rem. It ties with the integrations wall's between-group
   figure there, and on a phone the sections are already separated by the fold. */
.dfx-feature-group {
	margin-bottom: 6rem;
}

.dfx-feature-group__title a {
	color: inherit;
	text-decoration: none;
}

.dfx-feature-group__title a:hover,
.dfx-feature-group__title a:focus {
	color: var(--dfx-color-brand);
}

/* The summary sits BELOW the hairline, because the hairline is a border-bottom on
   the h2 that precedes it in the DOM and no margin trick changes that order.

   An earlier version pulled it up with `margin-top: -2rem` against the title's
   2.5rem bottom margin, on the theory that the line belonged under the label and
   its description together. It cannot: all that did was tighten the gap, and at
   ≤690px — where the shared title rule drops to 1.75rem — it netted -4px and the
   summary collided with the border above it. If the line ever should enclose both,
   the border has to move off the h2 and onto a wrapper.

   So: normal flow, sitting under the rule as intro copy for the group. */
/* THE GAP ABOVE IT IS THE TITLE'S MARGIN, so it is closed from the title's side and not
   this one — the block above records the failed attempt from here, where `margin-top:
   -2rem` only tightened the gap and collided with the rule at ≤690px.

   0.75rem IS THE INTEGRATIONS FIGURE, not a value chosen here. A workflow group on this
   archive and a category group on the integrations wall are the same object — a linked
   term heading, a line of term description, then the term's contents — so they take one
   treatment. See `.dfx-integrations-grid--summaries .dfx-integrations-grid__title--group`,
   which states the same 0.75rem for the same reason: with a description present the
   heading no longer needs the full section gap, because the paragraph is what separates
   the label from the content.

   `:has(+ …)` BECAUSE THE TITLE COMES FIRST IN THE DOM and the margin to change is its.
   Integrations does this with a `--summaries` class on the grid, set when the element is
   configured to show descriptions; here it is per group, because a workflow term may or
   may not have one and the archive renders all fourteen either way. A group whose term
   has no description keeps the 2.5rem the other twelve section titles take, since there
   the next thing IS the grid.

   0-2-0, so it outranks the shared title rule at 0-1-0, and no `.row .col` doubling is
   needed — this archive is a native template, not a WPBakery column, so the Salient
   `.row .col h3` rule the integrations title has to beat does not apply. No :has()
   support leaves the old 2.5rem — a looser gap, not a broken one. */
.dfx-feature-group__title:has(+ .dfx-feature-group__summary) {
	margin-bottom: 0.75rem;
}

/* FOUR STATED COLUMNS, NOT auto-fit, and the count is the change — the gaps are
   untouched. At the 1100px content measure `auto-fit, minmax(17rem, 1fr)` resolved to
   three tracks and could not reach four: four 272px floors plus three 40px gutters is
   1208px. So the floor was deciding the count, and the only way to buy a fourth column
   by lowering it is to set a floor narrow enough that a 900px container takes four too.

   THE SECOND THING THIS FIXES is the reason `--fixed` exists at all, quoted there: with
   auto-fit, a group holding two features rendered as two 530px half-width entries
   directly under a row of thirds. Fourteen workflow groups on the archive, several of
   them short, so the page changed its column width from section to section. A stated
   count means every entry on the archive sits on the same grid regardless of how many
   its group has.

   NOT FOLDED INTO `--fixed`, whose count is `var(--dfx-grid-cols, 4)`. Same number today,
   but that modifier's whole job is to be overridable per caller and this base is not —
   and its 2.5rem/4em gap belongs to entries carrying a badge and a "Learn more", which
   these do not.

   ROWS AT 2.5rem, NOT 1.5rem, and the argument is the one `--fixed` already makes about
   its own row gap: the gap between two entries has to beat the largest gap INSIDE one, and
   0.35rem is all that separates a name from its description. At 24px — with names wrapping
   to two lines across most of this archive — the second row read as a continuation of the
   first rather than as new items, which is proximity working backwards. It also now
   matches the column gap, so the grid has one figure instead of two. */
.dfx-feature-index {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 2.5rem;
}

.dfx-feature-index__item {
	margin: 0;
	padding: 0;
}

.dfx-feature-index__name {
	display: block;
	font-family: var(--dfx-font-heading);
	/* READS THE TOKEN, and it was a literal 1rem until the scale was re-anchored —
	   naming a role and then not reading its token is how a scale grows exceptions
	   nobody chose.
	   NO LONGER THE SAME SIZE AS .dfx-feature__name, which dropped to h6 by request
	   for the product list's narrow columns. This archive entry has a wider column and
	   keeps h5; the divergence is deliberate rather than the drift that was fixed here
	   before. */
	font-size: var(--dfx-size-h5);
	font-weight: var(--dfx-weight-emphasis);
	/* The small-heading leading, matching the step on the line above. Same band as
	   .dfx-feature__name uses, one step up in size. */
	line-height: var(--dfx-line-height-heading-small);
}

.dfx-feature-index__desc {
	display: block;
	margin-top: 0.35rem;
	color: var(--dfx-color-text-muted);
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-ui);
}

/* NOTHING HERE ANY MORE. The badge sat below the name on its own line, spaced by
   `margin: 0.35rem 0 0` — the names run to two lines often enough that an inline chip pushed
   the description down unevenly across the grid. It reads as a row in the card rather than a
   qualifier on the name, though, and it made the page disagree with itself about what a chip
   is, so the badges moved INTO .dfx-feature-index__name and take the product card's
   treatment. See index-item.php. */

/* THE STEP auto-fit USED TO DO FOR FREE, and stating the count is what makes it
   necessary — four fixed tracks in a 900px measure is a 205px column, which a feature
   name wraps to three lines inside. 999px and two columns, the boundary and the count
   `.dfx-grid--products` and `.dfx-feature-index--fixed` both take, so the three bands
   step together rather than each at its own width.

   BEFORE the 690px block below, because both are 0-1-0 and load order is all that
   separates them. */
@media (max-width: 999px) {
	.dfx-feature-index {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 690px) {
	/* THE ROW GAP DOES NOT TIGHTEN HERE, which is the opposite of the usual instinct and
	   the same call `--fixed` makes at this width. Every gap on a single-column stack is
	   between two FULL-WIDTH items, and the items are taller on a phone because every
	   description wraps further — so it needs at least the desktop row gap, not less. The
	   shorthand collapses to the row figure because 2.5rem of gutter does nothing with no
	   second column. */
	.dfx-feature-index {
		grid-template-columns: 1fr;
		gap: 2.5rem;
	}

	.dfx-feature-group {
		margin-bottom: 3rem;
	}

	.dfx-feature-single__products,
	.dfx-feature-single__workflows,
	.dfx-feature-single .dfx-product__integrations,
	.dfx-feature-single__content {
		margin-bottom: 2.5rem;
	}
}

/* --- Feature index, fixed columns -------------------------------------------- */
/* THE CARD SURFACE IS GONE, AND WITH IT MOST OF THIS BLOCK. What is left is a column
   count, which is the only thing this modifier was ever needed for.

   WHAT WENT: a Signal White fill, a hairline, a raised radius and shadow, a hover shadow,
   1.25rem of padding, a flex column, a name dropped to 16px so it would not shout inside
   250px, and a "Learn more" pinned to the foot behind a full-bleed divider. Ten declarations
   to make a feature look like a purchasable thing. index-item.php's own header already
   argued the principle — "a feature is a smaller claim and there are twenty-nine of them" —
   and the card treatment was the exception to it; the exception is what came out. The band
   now reads like the workflow grid: name, one line, and a "Learn more" under it.

   THE LINK ITSELF STAYED. Only its PINNING went — see the `__footer` rule below. The
   distinction matters because "remove the card" and "remove the call to action" look like
   one change from the outside and are not.

   WHY THE MODIFIER SURVIVES AT ALL. The base rule is `auto-fit, minmax(17rem, 1fr)`, and
   auto-fit renders a two-add-on product as two half-width entries under a row of quarters
   — the reason .dfx-grid states its counts too. So this states the count and inherits
   everything else, which is why there is one declaration where there were four.

   THE COUNT IS A VARIABLE WITH 4 AS ITS FALLBACK, so the related-products band — which
   writes nothing — is unchanged, and the Feature List element can ask for three when a page
   runs the grid inside a narrower column. Same convention and same property name as the
   products grid above, deliberately: two ways to say "how many columns" is one to get wrong.

   WIDE COLUMNS, FROM THE WORKFLOW GRID'S 4em, because that is what makes each item read as
   a column entry rather than a cell in a mesh — the argument on `.dfx-workflow-grid__items`,
   and this band is now the same kind of object. Not folded into that shared selector,
   though: the column count here is a variable and there it is a literal, so sharing the
   rule would mean one of them overriding the other immediately.

   BUT NOT ITS 1em ROW GAP, WHICH WAS THE WRONG HALF TO BORROW. A workflow cell is two
   things — a name and one line — so 1em clears it. An entry here is four: a name, a badge
   that often wraps to its own line, a description that runs to two or three, and a "Learn
   more". At 1em the second row read as a continuation of the first rather than a new item,
   which is proximity doing the opposite of what it is for.

   2.5rem, AND IT IS NOT AN ARBITRARY BIGGER NUMBER. The gap between items has to beat the
   largest gap INSIDE one, and 0.35rem is what separates name from description from link —
   so the row gap is what says "new item" against a stack of lines that all say "same item".
   2.5rem is already the figure the section titles take beneath them, so the band's internal
   rhythm and the page's agree. Also the base rule's column gap, for what that is worth.

   THE CARD DID THIS WORK WITH AN EDGE, which is why the old 2rem was enough and this is
   not a regression introduced by loosening the gap. A surface and a hairline said where one
   item stopped; with those gone the only thing left to say it is space.

   RENAMED FROM `--cards`, WHICH IS THE POINT OF THE RENAME. A modifier called cards that
   draws no card is the kind of name somebody reasons from a year later. --fixed says the
   one thing it still does: a stated column count against the base rule's auto-fit. */
.dfx-feature-index--fixed {
	grid-template-columns: repeat(var(--dfx-grid-cols, 4), minmax(0, 1fr));
	gap: 2.5rem 4em;
}

/* NO `> *` MARGIN RESET ANY MORE, AND NOTHING REPLACES IT. It existed because the card was
   a flex column: `gap` ADDS to margins rather than replacing them, so `__desc`'s 0.35rem
   stacked on top of the 0.625rem gap. With the flex column gone the entries are ordinary
   blocks and those margins are the spacing — the same margins the archive index has always
   used, which is what makes the two surfaces agree now instead of one cancelling them.

   Also gone: a name dropped to --dfx-size-h6. The reason was "an 18px name over 14px copy
   is the whole card shouting inside 250px", which was true of a 250px card and is not true
   of a column entry, so the base --dfx-size-h5 pairing applies here.

   THE PRODUCT FEATURE LIST NO LONGER AGREES, and that is current rather than stale: it
   dropped to h6 by request, for the same crowding argument, in columns a quarter of a
   container wide. This band keeps h5. */

/* THE NAME IS A PLAIN LINK, because the arrow is on the "Learn more" below it — both
   callers pass `cta => true`, which is index-item.php's "the CTA moves the arrow rather
   than adding a second one". Two arrow links to one destination in one entry is the same
   mark twice.

   `inherit` has to be named, for the reason .dfx-card__title a records: Salient's generated
   `body a { color: … }` is 0-0-2 and beats brand-base. Baltic on hover, matching the arrow
   link below rather than brass — brass is 2.29:1 on a light fill. */
.dfx-feature-index__link,
.dfx-feature-index__name-text {
	/* THE GAP BEFORE THE BADGE TRAILS THE TITLE, exactly as .dfx-card__title a does it, and
	   for the reason recorded there: a leading margin on the chip still renders at the start
	   of a wrapped line, so a badge that dropped to its own line sat indented from the name.
	   A trailing margin on the element before it does not.

	   0.667em, THE SAME FIGURE THE CARD USES, which is what makes this proportional rather
	   than matched. Against the card title's 18px it resolves to 12px and against this name's
	   16px to 10.7px — each gap in step with the type it separates, from one number. Stating
	   10.7px here would be the card's ratio re-derived by hand and wrong the next time either
	   step moves.

	   __name-text is the unlinked title's wrapper. A bare text node cannot take a margin, and
	   an unpublished feature is the normal case before launch — see index-item.php. */
	margin-inline-end: 0.667em;
}

.dfx-feature-index__link {
	color: inherit;
	text-decoration: none;
}

.dfx-feature-index__link:hover,
.dfx-feature-index__link:focus {
	color: var(--dfx-color-brand);
}

/* THE "Learn more" STAYS AND STOPS BEING A FOOTER, which is the whole of what changed
   here. It used to be pinned to the bottom of the card by `margin: auto` and separated by a
   divider bled through the card's 1.25rem padding with a negative inline margin. All three
   of those describe a card: `auto` only pushes when a flex column has spare height, and a
   full-bleed rule needs an edge to bleed to.

   SO IT IS A LINE IN THE FLOW NOW, sitting under the description the way any other line
   would, at the same 0.35rem `__desc` uses against the name. No border, no pinning. The
   consequence worth stating: the links no longer align across a row, because each one
   follows its own description rather than the tallest. That is what "inline" costs and it
   is the right trade once there is no card edge for a ragged row to look ragged against.

   BASE LEVEL, NOT SCOPED TO `--fixed`, because the footer is markup that only exists when a
   caller passes `cta => true` and only the two banded callers do. The archive and the
   workflow page render no footer at all, so a modifier scope would be guarding against
   nothing. */
.dfx-feature-index__footer {
	margin-top: 0.35rem;
}

/* Size and weight only. Color, the arrow, the missing underline and the hover all come
   from .dfx-feature-link in the Link arrow block, so this link cannot drift from the
   thirty others on the site that use it. */
.dfx-feature-index__cta {
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-emphasis);
}

/* Two, on the boundary .dfx-grid--products steps at, so the bands step together. */
@media (max-width: 999px) {
	.dfx-feature-index--fixed {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* AFTER both queries above: all three are 0-1-0, so load order is the only thing
   separating them, and without this the two-column rule would still match at phone width.

   ONE VALUE AT ONE COLUMN, AND IT IS THE ROW GAP RATHER THAN A SMALLER ONE. 4em of column
   gutter is invisible with no second column, so the shorthand collapses to the figure that
   still does something. It was 1.5rem here while the rows were 1em, which made sense then
   and is backwards now: every gap on a single-column stack is a gap between two full-width
   items, so it needs at least what the desktop rows get, not less. Tightening at narrow
   widths is the usual instinct and it is the wrong one here — the items are TALLER on a
   phone, because every description wraps further. */
@media (max-width: 690px) {
	.dfx-feature-index--fixed {
		grid-template-columns: 1fr;
		gap: 2.5rem;
	}
}

/* ============================================================================
   FOOTER SURFACE
   ============================================================================
   White, and flush to the page — no hairline across the top.

   Specificity below is written (id-class-element), the same convention as the
   footer list-spacing table further down.

   BACKGROUND: --dfx-color-surface-raised. That token is named for cards — a
   surface sitting above the page — and #FFFFFF is the only pure white in the
   ramp; the footer now stands in exactly that relationship to the page, so it
   takes the same token rather than introducing a second name for one value.

   Salient emits the Theme Options footer color as

     #footer-outer { background-color: #F5F7F9 !important }

   at 1-0-0, so beating it needs !important at equal-or-higher specificity.
   `body` is prepended for no other reason — 1-0-1 is the cheapest thing that
   outranks it.

   NOT GATED ON [data-custom-color="true"], AND THAT IS THE WHOLE POINT OF THIS
   SELECTOR. The first version of this rule used that attribute to reach 1-1-0,
   reasoning that it is on the footer precisely BECAUSE the custom footer color
   scheme is switched on — the same condition that emits the rule being
   overridden — so the two would appear and disappear together. Elegant, and
   wrong in the only way that mattered: the scheme is a Theme Options setting,
   which means it lives in the WP database, which means it is per-environment.
   Staging reports data-custom-color="false" and a #252525 footer, so the gated
   rule matched nothing there and the footer would have stayed dark through a
   deploy that shipped the CSS correctly. The condition it was pairing with is
   not a property of the code, it is a property of one database.

   So the appearance is stated unconditionally here and does not ask the DB's
   permission. Where the two disagree this wins, which is the direction that
   makes a rebuilt environment converge on the design instead of on whatever
   its options table happens to hold.

   THE COPYRIGHT BAR GOES WITH IT. Salient paints that separately
   (`body #footer-outer #copyright`, 2-0-1, no !important) and the footer reports
   data-matching-section-color="true" — the two are meant to read as one block, so
   leaving the bar tinted would put a white footer on a gray strip. Identical
   specificity to the parent's rule, so !important is what settles it rather than
   source order — which matters, because Salient's is generated into
   uploads/salient/ and its load position is not ours to rely on.

   THE HAIRLINE IS DELIBERATELY ABSENT, not forgotten. There used to be a 1px rule
   across the top of the footer's content row, and it was doing real work when the
   footer was #F5F7F9 on a light page. On the current templates the section above
   the footer is dark, so the footer's own edge — white against Obsidian — already
   separates the two far more strongly than any 1px line, and drawing one there
   only muddied the join. If a light-background template ever lands above the
   footer and the seam goes soft, this is the rule to bring back:

     #footer-outer #footer-widgets > .container > .row {
       border-top: 1px solid color-mix( in srgb, currentColor 10%, transparent );
     }

   ON THE ROW, NOT THE CONTAINER, if it does come back. Both are inset from the
   full-bleed #footer-outer, but a border draws on the BORDER box: the container's
   is 1280px wide including its own 40px of padding, so a rule there overhangs the
   footer's own columns by 40px each side. The row is the 1200px content measure —
   the same 159→1359 line the main grid and every .dfx-*__title hairline sit on.
   currentColor at 10% rather than a literal rgba so it follows the footer's text
   color instead of assuming a light background; against #424752 text it resolves
   to #E3E5E8, which is --dfx-color-border-subtle to within a rounding error.

   TO GO BACK TO A TINTED FOOTER, point these at --dfx-color-surface rather than
   editing Theme Options — the DB value does not survive a Kinsta rebuild and this
   file does. */
body #footer-outer,
body #footer-outer #copyright {
	background-color: var(--dfx-color-surface-raised) !important;
}

/* CLEARANCE ABOVE THE FOOTER — the gap the hairline used to sit in.

   Salient gives `.container-wrap` 40px of bottom padding:

     body.page-template-template-portfolio-php .container-wrap,
     body.single-portfolio .container-wrap,
     body.tax-project-type .container-wrap,
     body[data-bg-header="true"] .container-wrap { padding-bottom: 40px }

   The fourth selector is the one that matches here; the three portfolio ones never
   apply on this site. 40px was too tight: the last section on the page ended up
   almost against the footer, which opens with 75px of its own top padding on the
   widget row, so the join was lopsided — 40 above against 75 below.

   5rem — 80px — against that 75px, so the seam sits optically centerd in its own
   gap. Doubling is what balances it; 2.5x was considered and would have gone
   top-heavy at 100 above against 75 below.

   THIS SURVIVES THE HAIRLINE. The value was picked to balance the two paddings
   either side of the join, and both are unchanged now that no line is drawn on
   it — the white footer edge lands in the same place the border did.

   ONLY padding-bottom. Salient sets padding-top and a margin-top override in the
   same declaration, and both are load-bearing — the `padding-top: 0 !important`
   companion rule is what lets a full-bleed header open at the top of the viewport.

   Same specificity as Salient's rule, 0-2-1, winning on source order because
   dfx-components enqueues at priority 100 and main-styles at 20. Matching rather
   than escalating keeps it overridable by anything more specific later. */
body[data-bg-header="true"] .container-wrap {
	padding-bottom: 5rem;
}

/* ============================================================================
   FOOTER LINK COLOR
   ============================================================================
   Every link in the footer is Pewter, and Pewter is the lightest the ramp goes
   while still clearing AA.

   THE FOOTER HAD TWO LINK COLORS BECAUSE SALIENT PAINTS IT IN TWO PLACES, from
   two separate Theme Options fields, and neither knows about the other:

     #footer-outer, #footer-outer a:not(.nectar-button)    #424752   9.31:1
     #footer-outer #copyright a:not(.nectar-button)        #9AA0A6   2.64:1

   both !important. So the widget menus rendered at the same weight as footer body
   copy while the legal menu beside the copyright line rendered nearly invisible —
   the two ends of the neutral ramp, in one footer, decided by which region a link
   happened to sit in. Now both are --dfx-footer-link.

   ON THE AA FLOOR BY REQUEST, VIA --dfx-footer-link, which is Nickel #6F7688 at
   4.54:1 on white. On white the ramp reads:

     Slate Graphite  #424752   9.31:1   <- footer body copy, and the hover color
     Pewter          #676E7E   5.11:1   the muted text role
     Nickel          #6F7688   4.54:1   <- footer links
     Steel Gray      #9AA0A6   2.64:1   fails
     Soft Stone      #C8CBCF   1.63:1   fails

   Nickel is not a round number and cannot be nudged: one 8-bit step lighter on the
   same hue is #6F7789 at 4.49:1, which fails. It is the edge, which is what was
   asked for.

   THE PREVIOUS VERSION OF THIS RULE USED PEWTER AND ARGUED AGAINST GOING LIGHTER,
   on two grounds. Both are recorded rather than deleted, because both are still
   true and were accepted rather than refuted. First, the palette had nothing
   between Pewter and failing, so hitting 4.5:1 meant adding a color to the ramp —
   it now has one, named and documented in brand-tokens.css, which is the honest
   version of that cost rather than an inline hex. Second, sitting on the threshold
   leaves no headroom for antialiasing, a non-sRGB display, or a footer tinted a
   shade off white; Pewter's 5.11:1 had a ramp step in hand and this does not. If
   these ever need to move back, --dfx-footer-link is the one line to change.

   WHICH IS WHY IT IS ITS OWN TOKEN and not --dfx-color-text-muted. That role also
   paints card subtitles and hero eyebrows, several of them on Signal White, where
   Nickel resolves to 4.20:1 and fails. Keeping the threshold value behind a
   footer-specific name is what stops it leaking onto a surface it does not clear.

   TWO SELECTORS, ONE DECLARATION, and the pairing is not redundant. The copyright
   rule above is 2-1-1, so the widget-area selector at 1-1-2 loses to it inside
   #copyright no matter how the cascade is ordered — id count is compared first and
   1 < 2. Adding #copyright to a second selector takes that branch to 2-1-2. Each
   selector is sized against the parent rule it has to beat, which is why they look
   like near-duplicates and are not.

   THIS ALSO FIXES FOOTER LINK HOVER, which had been broken site-wide and was
   flagged on DSGN-597. Salient emits its footer colors with !important, killing
   its own `#footer-outer a:hover` — so every link down there had no hover state at
   all. The hover rule below carries !important for the same reason and restores it
   everywhere in one place.

   THE UNDERLINE IS THE POINT, not the darkening. A color-only hover would be the
   single affordance on these links, and a shift between two greys is not one that
   survives a bright screen. text-decoration needs no !important — Salient sets
   `text-decoration: none` on `a` without one, so specificity alone carries it.

   Hover darkens to Slate Graphite, skipping Pewter — two steps up the ramp rather
   than one, and deliberately. From a resting color sitting ON the AA floor, one
   step is Nickel to Pewter at 1.13:1, which is not a state change anyone would
   notice. Slate Graphite is 2.05:1 against Nickel and is also the footer's own body
   copy color, so a hovered link resolves to the text weight around it instead of
   overshooting past it. Still within the ramp, per the brand rule against inventing
   lightened or darkened variants. */
body #footer-outer a:not(.nectar-button),
body #footer-outer #copyright a:not(.nectar-button) {
	color: var(--dfx-footer-link) !important;
}

body #footer-outer a:not(.nectar-button):hover,
body #footer-outer a:not(.nectar-button):focus-visible,
body #footer-outer #copyright a:not(.nectar-button):hover,
body #footer-outer #copyright a:not(.nectar-button):focus-visible {
	color: var(--dfx-footer-link-hover) !important;
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/* --- The footer type scale, AND IT IS A DIFFERENT SITUATION FROM THE HEADER'S -----
   The header's sizes came from Theme Options and were gated on a field being in use.
   These are NOT. css/custom.php emits the footer's sizes as unconditional static CSS —
   `#footer-outer .widget h4 { font-size: 14px }` sits at custom.php:8707 in a plain
   block between two layout rules, and that file contains ZERO `attrs_in_use` gates
   against fonts.php's 31. So there is no option behind them to be set or cleared, no
   editor decision to respect, and nothing to lose by escalating. Child theme owns them
   outright.

   FOOTER NAV LINKS DROP 16px → 14px, which is the one judgment call in this block.
   They were the only chrome on the page still at body size, and a footer link column
   is the same KIND of thing as a megamenu column — now both read 14px, so the two
   navigation surfaces agree. The widget titles above them are already the 14px label
   step, so the column reads as caps label over sentence-case links at one size, which
   is the relationship the megamenu now has too.

   THE COPYRIGHT LINE GOES TO THE CAPTION STEP at 13px. Salient's static value is 12px
   and it was rendering 14px, so it was already being overridden by something on the way
   through — 13px is the step that role actually wants, and stating it here means the
   number is decided in one place instead of arrived at. Its 1.57 leading was inherited
   prose leading on a single line of fine print.

   COLOR IS DELIBERATELY ABSENT, for the reason the block above gives: two of these
   are painted from Theme Options and adding color here would make this the third place
   footer color is decided. Size only.

   font-size NEEDS !important AND line-height DOES NOT, which is the third time this
   exact asymmetry has shown up down here. Salient ships
   `.material #footer-outer .widget li a { font-size: 1rem !important }`, so the first
   version of this rule landed its leading and silently lost its size — the symptom
   already recorded against the card button and the footer widget h4's font-weight: a
   rule where most declarations apply and exactly one does not. Check the computed size,
   not just that the rule appears in devtools. */
body #footer-outer #footer-widgets .widget a:not(.nectar-button) {
	font-size: var(--dfx-size-body-sm) !important;
	line-height: var(--dfx-line-height-ui);
}

body #footer-outer #copyright,
body #footer-outer #copyright p {
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
}

/* The legal links inherit the caption size from #copyright above, but Salient pins
   their leading with `#footer-outer #copyright li a { line-height: 22px }` — 1.69 on
   13px text. Single-line links, so it costs nothing visually; corrected anyway so the
   whole footer reports one leading and a future two-line legal menu does not surprise
   anyone. No !important needed here, unlike the size above. */
body #footer-outer #copyright li a {
	line-height: var(--dfx-line-height-ui);
}

/* NOT LINKS, AND STILL FAILING, recorded here because it is the next thing to
   look at and the fix is not in this file. The footer's non-link text comes from
   Theme Options — 2nd Footer Font Color paints the "Products" / "Services" column
   headings and Footer Copyright Font Color paints the tagline and the copyright
   line, both #9AA0A6, both 2.64:1 on white. That is under AA for normal text.
   Those are Redux values in the WP database, so they change in the options panel
   and not here — see the footer notes before reaching for CSS, because a rule
   added here would be the third place footer color is decided. The column
   headings get SMALLER just below, which makes their ratio matter more, not less. */

/* ============================================================================
   FOOTER COLUMN HEADINGS
   ============================================================================
   The "Products" / "Services" widget titles, matched to the megamenu's column
   headings — small, uppercase, tracked — instead of Salient's 16px title-case.

   THE MEGAMENU IS THE REFERENCE BUT NOT THE SOURCE OF THE VALUES, and that
   distinction is the whole decision here. Its column headings render 11.2px / 600 /
   uppercase / 0.13em, which looks like a considered spec and is not: the span
   carries Salient's `.nectar-inherit-h6`, so those numbers come from the parent
   theme's h6 Theme Options fields. Copying them would have put an off-scale value
   in a second place and left the two able to drift apart the day anyone touches
   Salient's h6 settings.

   So this takes OUR CHROME-LABEL STEP instead — --dfx-size-label at 14px, with 0.14em
   and weight 600. It is shared with .dfx-eyebrow and the "Trusted by" separator, which
   are the same kind of thing: a label that is furniture rather than document structure.

   IT USED TO READ --dfx-size-h6 AND THAT WAS THE BUG, though it took h6 moving to show
   it. While h6 was 13–14px the two were interchangeable; when h6 became 16px this
   followed it up and the footer column headings started competing with the links under
   them. A widget title is not a rung of the outline, so it should never have been on a
   heading step. The two tokens now say which is which.

   RESTATED RATHER THAN INHERITED, for the same reason the separator restates it: this
   element is Salient's `.widget h4`, so uppercase and tracking cannot be picked up from
   the h6 label block. That block is the source; this is a copy kept in step by hand.

   THE SIZE READS A TOKEN, so four successive changes moved this from 13px to 14.4 to 14
   to 16 and now back to 14, with no edit to the rule any time. The numbers in this
   comment are the part that needs hand-updating — which is the arrangement worth having.

   THE TWO WILL NOT BE PIXEL-IDENTICAL WITH THE MEGAMENU, chosen deliberately over
   matching exactly. Making them agree by construction means moving the megamenu onto
   the same step, which is a header change and needs checking where the megamenu
   reflows. So the 2.8px gap to its 11.2px is a decision rather than an oversight, and
   the fix if it ever matters is now obvious AND has a proper target: point both at
   --dfx-size-label. That is a better answer than the --dfx-size-h6 this note used to
   give, because the megamenu column heads are chrome too.

   COLOR IS SET HERE, AND LEAVING IT OUT WAS A BUG. The first version of this rule
   deliberately did not set color, reasoning that the footer headings were #9AA0A6
   from 2nd Footer Font Color and the megamenu headings were #9AA0A6 too, so the two
   already agreed on the one property the rule need not touch. That was measured on
   dealerfx.test and it is true there and nowhere else. Salient only emits the
   2nd Footer Font Color rule when the custom footer color scheme is switched on,
   and that is a per-environment Theme Options flag: staging reports
   data-custom-color="false", so the heading color fell through to Salient's own
   default —

     #footer-outer .widget h4 { color: #777 }   1-1-2, no !important

   — a pure neutral #777777 that is in no Dealer-FX palette. So the headings matched
   the megamenu on local and were visibly greyer on staging, from one stylesheet.

   THIS IS THE SECOND TIME A THEME-OPTIONS DEPENDENCY HAS SHIPPED A DIFFERENT FOOTER
   PER ENVIRONMENT, after the [data-custom-color] gate on the background rule above,
   and the lesson generalises past both: if the design decides a property, this file
   states it. Not setting a property is also a decision, and it hands the answer to
   whichever database the page happens to render from.

   --dfx-label-ink, WHICH REPLACED --dfx-steel-gray AND FIXED THE FAILURE BELOW. Matching
   the megamenu's #9AA0A6 was the original requirement and it was met — at 2.64:1, under
   AA, because the megamenu itself fails. Matching something broken is not a requirement
   worth keeping once it is named out loud. The label ink resolves to Pewter at 4.72:1 on
   light and re-points itself on dark surfaces via the escape hatches in brand-base.css,
   which a flat gray could not do. The megamenu is now the only half of the pair failing,
   and the note below is where that is tracked.

   !important at 2-2-1 clears both branches at once: Salient's #777 default at 1-1-2
   with no !important, and `#footer-outer #footer-widgets .widget h4` at 2-1-1 WITH
   !important, which is the 2nd Footer Font Color rule on any environment that has
   the scheme on. Whichever of those exists, this outranks it, so the two
   environments converge.

   NOW 4.72:1 AND PASSING — this is the half that got fixed. It sat at 2.64:1 for a
   long time on the reasoning that matching the megamenu mattered more, with a note
   saying "moving both to Pewter is the fix when it is wanted". Half of that is done:
   this rule reads --dfx-label-ink. The other half is Salient's h6 color in the Theme
   Options panel, which is a database change and still outstanding, so the megamenu
   column heads remain under AA. The two regions no longer match, and that is the
   correct trade — they matched at a failing ratio before.

   font-family is stated rather than inherited because this is the label role, which
   brand-base defines against --dfx-font-body. Both resolve to Inter today, so it is
   a no-op — but if the heading family ever diverges from body, a label should follow
   the label role rather than the h4 it happens to be marked up as.

   NO LINE-HEIGHT AND NO MARGIN. Salient's 1.4 and 20px are both fine on a
   one-word label, and a fourth opinion on label leading is not worth the line.

   2-2-1, which clears the rules in play on size and tracking: Salient's
   `.widget h4` at 0-1-1, where the 16px came from, and brand-base's `.row .col h4`
   at 0-2-1, where the -0.02em heading tracking came from. Neither uses !important,
   so specificity alone carries those.

   font-weight IS THE ONE EXCEPTION, and it is worth knowing why it is here alone.
   Salient's generated stylesheet ships TWO rules for this element:

     #footer-outer .widget h4       color/font-size/font-weight:600/margin  1-1-2
     body #footer-outer .widget h4  font-weight: 500 !important             1-1-2

   The second exists to overrule the first and uses !important to do it, so 2-2-1
   without one lost that single property while every other declaration in this rule
   landed. THAT SYMPTOM IS THE SIGNATURE, and this file has recorded it before on
   the card button: a rule where most declarations apply and exactly one does not is
   a single property lost to something more specific, not a rule that failed to
   load. Checked against the generated file rather than reasoned about, which is the
   standing rule for anything Salient paints from Theme Options. */
#footer-outer #footer-widgets .col .widget h4 {
	font-family: var(--dfx-font-body);
	font-size: var(--dfx-size-label);
	font-weight: var(--dfx-weight-emphasis) !important;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	/* !important RETAINED — Salient emits the footer's colors with it, so this loses
	   without matching it. It was dropped by accident during the Steel Gray repoint and
	   caught by re-reading the diff. The megamenu twin needs no !important, because
	   nothing declares !important on color for .nectar-inherit-h6. */
	color: var(--dfx-column-head-ink) !important;
}

/* ============================================================================
   FOOTER COLUMN GUTTER AND WIDTHS
   ============================================================================
   The gap between footer columns goes from Salient's 2% to 5%, and the row is
   re-divided so all four columns are sized to the text they actually hold.

   THE FOURTH COLUMN IS NO LONGER EMPTY. This block previously bought the wider
   gutter by squeezing the last column to 10.5%, on the grounds that it held a
   widget with no content and measured 1px tall. It now holds the OEM Programs
   menu, so 10.5% — 115.5px against a 1100px container — was wrapping its heading
   ("OEM Programs" needs 125px) and its first link ("Toyota SmartPath", 113px).
   That is what the old comment predicted would happen and told the next reader to
   redo, so this is the redo.

   Salient's desktop preset is

     #footer-widgets[data-cols="5"] .container .row > div              width: 19.5%
     #footer-widgets[data-cols="5"] .container .row > div:first-child  width: 35%
     .col                                                             margin-right: 2%

   totalling 35 + 19.5x3 + 2x3 = 99.5%, and the budget stays 99.5% here.

   THE WIDTH COMES OUT OF THE COMPANY COLUMN, which is the only real slack left in
   the row. Measured against the 1100px container, longest string per column:

     1  brand      logo 223px, tagline reflows freely     35%    385px
     2  products   "Service Intelligence Platform™" 198px  21%    231px
     3  company    "Terms of Service" 113px                14%    154px
     4  OEM        "OEM Programs" 125px                    14.5%  159.5px

   New total: 35 + 5 + 21 + 5 + 14 + 5 + 14.5 = 99.5%. Column 3 was carrying 214.5px
   for 113px of text — 100px of slack — and gives up 5.5% of it; column 2 gains 1.5%
   and column 4 gains 4%.

   BRAND COLUMN AND GUTTER ARE BOTH UNTOUCHED, which was the point of taking it from
   column 3. 35% keeps the tagline at four lines, and 5% keeps the gutter the earlier
   pass argued for.

   COLUMN 2 GOT WIDER, NOT JUST COLUMN 4. At 19.5% it was 214.5px against 198px of
   text, which holds at a 1100px container but not at the bottom of this media query:
   the container is fluid below 1100px, so at a 1000px viewport 19.5% is 195px and
   "Service Intelligence Platform™" wrapped. 21% is 210px there. Every column was
   checked at a 985px container (a 1000px viewport with a scrollbar) as well as at
   1100px, and nothing wraps at either.

   WHY nth-child AND NOT :last-child FOR THE WIDTHS. Salient's width rules are
   1-3-1; the nth-child selectors here are 1-4-1, so they win on specificity with no
   !important. `margin-right: 0` still has to be restated on :last-child because
   Salient's own reset is `.col:last-child` at 0-2-0 and loses to the 1-3-1 gutter
   rule above — its version for this region is scoped to the 691–999px query and does
   not apply at this width.

   SCOPED TO >=1000px DELIBERATELY. Between 691 and 999px Salient throws the preset
   away and runs a two-up layout — `#footer-widgets .container .col` at 48% with the
   same 2% margin, totalling 98% — which is a different arithmetic that this must not
   touch. Below 691px the columns are 100% and stack, where a horizontal gutter means
   nothing.

   ASSUMES EXACTLY THE FOUR WIDGET AREAS CURRENTLY RENDERED. data-cols="5" is the
   name of Salient's preset, not a count of what exists — with five populated areas
   its own numbers already overflow (35 + 19.5x4 + 2x4 = 121%). A fifth column means
   redoing this arithmetic, and there is no room left to do it by shaving: the four
   columns are now sized to their content, so the honest fix at that point is to drop
   the footer to fewer columns in Theme Options.

   THE SAME GOES FOR LONGER COPY. The tightest column is 2, at 231px against 198px
   of text, so a product name longer than "Service Intelligence Platform™" by more
   than about three characters wraps. Column 3 has the remaining slack to give. */
@media only screen and (min-width: 1000px) {
	#footer-widgets[data-cols="5"] .container .row > div {
		margin-right: 5%;
	}

	#footer-widgets[data-cols="5"] .container .row > div:nth-child(2) {
		width: 21%;
	}

	#footer-widgets[data-cols="5"] .container .row > div:nth-child(3) {
		width: 14%;
	}

	#footer-widgets[data-cols="5"] .container .row > div:nth-child(4) {
		width: 14.5%;
	}

	#footer-widgets[data-cols="5"] .container .row > div:last-child {
		margin-right: 0;
	}
}

/* ============================================================================
   FOOTER LIST SPACING
   ============================================================================
   Links in the footer widgets sat 8px apart — 4px of padding above and below each
   item — which read as a block of text rather than a list of separate targets.
   Now 6px each side, so 12px between adjacent links.

   EVERY LIST IN THE FOOTER COLUMNS, not just the nav menu widgets. Scoped to
   `.col ul li` — the same scope Salient's own rule uses — so a categories widget,
   a recent-posts widget or a hand-written list in a text widget all get the same
   rhythm as the menus. Today only the Products menu is populated (the Services
   widget has a title and no items yet), which is exactly why this is written by
   region rather than by widget type: the next list added to the footer should not
   need a new rule.

   Social rows are excluded. `ul.social` in the copyright bar is a horizontal row
   of icons, where vertical padding on each item does not add space between them —
   it just makes the row taller. Nested sub-menu items ARE included: `li` is a
   descendant selector rather than a child one, so a second-level link is spaced
   like a first-level one.

   WHY THIS RULE IS UGLY, AND WHY IT HAS TO BE. Three of Salient's rules land on
   these items and two of them use !important:

     .material #footer-outer #footer-widgets .col ul li      padding: 4px 0 !important   2-2-2
     #footer-outer #footer-widgets .widget.widget_nav_menu li padding: 0 !important      2-2-1
     #footer-outer #footer-widgets .col ul li:first-child     padding-top: 0 !important  2-3-2

   The `.material` one wins today because this site runs the Material skin, and
   it is the one with the highest specificity of the three. Beating an !important
   requires another !important, and beating 2-2-2 requires the id chain — hence
   the shape below. It is written to clear all three rather than just the one
   that happens to be winning, so switching skins in Theme Options cannot quietly
   restore the old spacing.

   The `body.material` and bare variants are both listed because the skin class
   may or may not be present; whichever matches, the specificity clears 2-2-2. */
body.material #footer-outer #footer-widgets .col ul:not(.social):not(.nectar-social) li,
#footer-outer #footer-widgets .col ul:not(.social):not(.nectar-social) li {
	padding-top: 0.375rem !important;
	padding-bottom: 0.375rem !important;
}

/* The first item keeps its flush top, which is Salient's own behavior and worth
   preserving: padding here would push the whole list down relative to the widget
   title beside it, and the misalignment reads as a mistake. Restated rather than
   inherited, because the rule above now outranks the :first-child rule that used
   to do this. */
body.material #footer-outer #footer-widgets .col ul:not(.social):not(.nectar-social) li:first-child,
#footer-outer #footer-widgets .col ul:not(.social):not(.nectar-social) li:first-child {
	padding-top: 0 !important;
}

/* ============================================================================
   COPYRIGHT BAR MENU
   ============================================================================
   The legal menu printed beside the copyright line — markup from
   dfx_footer_legal_menu(), see inc/footer-legal-menu.php.

   IT USED TO NEED ALMOST NO CSS, and that stopped being true when the menu moved
   out of the right-hand span_7 column to sit beside the copyright line in span_5.
   Salient's generated stylesheet lays out the copyright columns for its social
   row, and every one of those rules is written against `.col ul` rather than
   `ul.social`, so our list inherits the lot whether we want it or not:

     #footer-outer #copyright .col ul          float: right      (desktop)
     body #footer-outer #copyright .col ul     float: left       (max-width 690px)
     #footer-outer #copyright li               float: left; margin-left: 20px

   While the menu sat in span_7 that inheritance was exactly right and this file
   declared nothing. In span_5 the same `float: right` is actively WRONG: it
   drives the list to the right edge of the LEFT-hand column, stranding it in the
   middle of the footer with a gap between it and the copyright text it belongs
   to. So the float has to be undone here, and the column has to do the layout.

   FLEX ON THE COLUMN, NOT A FLOAT ON THE NAV. The <nav> is a full-width block on
   purpose — see the note in inc/footer-legal-menu.php, it is a labeled region for
   assistive tech — so floating it would mean also handing it a width, and the
   copyright <p> beside it is a block that would then need clearing. One flex
   container on the column puts the <p> and the <nav> on one line, preserves
   source order, and declares no widths at all. Baseline rather than center
   because these are two runs of text at the same size: centering aligns their
   boxes and leaves the words looking a pixel out.

   SPECIFICITY, because the parent's rules are ID-heavy and easy to lose to.
   Salient's float sits at (2,1,1) on desktop and (2,1,2) under 690px. Adding the
   .dfx-footer-legal class reaches (2,2,1), which beats both — the ID counts tie
   and the class count decides. Note that `.dfx-footer-legal__list` alone would
   NOT have worked: at (2,1,0) it loses to the parent's (2,1,1) on the type
   selector, which is the sort of near-miss that reads as a broken override.

   What is left is color, and that is not decided here. */

/* THE 5/7 COLUMN SPLIT HAS TO GO, and this is the rule that actually made the
   menu sit beside the copyright line rather than under it.

   Salient sizes the copyright row with its 12-column grid: span_5 gets 40.5% and
   span_7 gets 57.5%. Measured on the built page at a 1100px container that is
   446px and 633px. The left column needs 489px — 236px of copyright text, the
   24px gap, and a 229px two-item menu — so it overflows its 446px by 43px and
   the menu wraps. Meanwhile span_7 holds five 20px icons, about 130px of content,
   in 633px. Half the row is empty and the half doing the work is short.

   Widening span_5 with a percentage would only move the cliff: the numbers above
   are one viewport and one menu, and the copyright text, the item count and the
   item labels can all change. A percentage split cannot express "as wide as its
   content needs" — flex can, so the row becomes a flex container and both
   columns size to content with the social icons pushed right. There is then no
   width to keep in sync with the content, which is the actual fix.

   ALIGN CENTER, NOT BASELINE, and deliberately. span_7's <ul.social> is floated,
   so that column has no in-flow line box and no first baseline — `baseline` here
   would fall back to its bottom margin edge and drop the icons, the same trap
   documented on the list items below. Centering aligns boxes instead of text and
   sidesteps it. Inside span_5, where nothing is floated any more, baseline is
   still correct and still used. */
#footer-outer #copyright .container {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	column-gap: 2rem;
	row-gap: 0.75rem;
}

/* THE CLEARFIX HAS TO BE SWITCHED OFF, or `space-between` above silently does the
   wrong thing. Salient clearfixes .container with `::before`/`::after` set to
   `content: " "; display: table`, which is inert while the container is a block —
   but pseudo-elements of a FLEX container become flex ITEMS. That makes four
   items where the markup shows two, and `space-between` puts equal space in the
   three gaps between them rather than one gap in the middle: measured 133px
   before span_5, 133px between the columns and 133px after the icons, so the
   whole row read as centered with the columns floating in the middle.

   Worth knowing how this presents, because it wastes time: getComputedStyle
   reports `justify-content: space-between` quite correctly, the margins are all
   zero and childElementCount is 2, so every value you check says the rule is
   applied and nothing explains the gaps. The extra items are invisible to all of
   them. 399px of free space landing in exactly three equal parts is the tell. */
#footer-outer #copyright .container::before,
#footer-outer #copyright .container::after {
	display: none;
}

/* Out of the grid: drop the float, the percentage width and span_5's 22px gutter,
   all of which the flex row above now owns. */
#footer-outer #copyright .container > .col {
	float: none;
	width: auto;
	max-width: 100%;
	margin: 0;
}

/* ONE SHARED 24px LINE BOX FOR ALL THREE, which is what actually puts the
   copyright text, the menu and the icons on a common middle.

   `align-items: center` on the row is not sufficient on its own, and it is worth
   saying why since it looks like it should be. Centring aligns BOXES, and the
   three boxes did not agree with their own contents:

     - Salient's global `p { padding-bottom: 1.5em }` is body-copy styling that
       leaks into the copyright line. At 13px that is 19.5px, plus a 3px top
       margin, so the <p> was a 41.3px box with its text riding high in it.
       Centring that box put the text 7.1px above the icons.
     - The menu links sit in a 24px box but had an 18.85px line-height, so
       box-centre and text-centre disagreed by 2.6px. Switching the column to
       `align-items: center` aligned the boxes and made the TEXT worse — the
       copyright line and the menu drifted 2.58px apart, having been exact.
     - The icons are `vertical-align: middle`, which seats a glyph on the
       baseline plus half the x-height — about 1.5px ABOVE the line box centre,
       not on it. So even with every box aligned they read low against the text.

   Giving the <p> and the menu links the same 24px line-height as the icons' box
   makes all three boxes 24px with their content centred the same way, and the
   column keeps `align-items: baseline` so the two text runs stay exact. Measured
   spread across all three afterwards: 0.01px.

   Do not "simplify" this to `align-items: center` on the row and nothing else.
   That is the version that was tried and it is off by 7px. */
#footer-outer #copyright .container > .col > p,
#footer-outer #copyright .col .dfx-footer-legal a {
	line-height: 24px;
}

#footer-outer #copyright .container > .col > p {
	margin-top: 0;
	padding-bottom: 0;
}

/* Centre the icon in its own box rather than trusting `vertical-align: middle`,
   which is the 1.5px described above. Flex on the <a> and not the <li>: the li's
   only child is the <a>, so centring the li moves nothing — the <i> is a
   grandchild. The .screen-reader-text span is absolutely positioned and stays a
   1x1 box, so it takes no part in the flex layout. */
#footer-outer #copyright .col ul.social a {
	display: flex;
	align-items: center;
	justify-content: center;
}

#footer-outer #copyright .col.span_5:has(> .dfx-footer-legal) {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 1.5rem;
	/* Only applies once the items wrap, which is what makes the media query that
	   used to live at the bottom of this section unnecessary — see there. */
	row-gap: 0.75rem;
}

/* Shrink the nav to its list. As a block it would eat the whole column and push
   the flex gap open to nothing visible. */
#footer-outer #copyright .col .dfx-footer-legal {
	width: auto;
}

/* THE LIST ITEMS HAVE TO COME OUT OF FLOAT TOO, and the reason is not obvious
   enough to leave unwritten. Undoing `float` on the <ul> alone leaves the
   parent's `#footer-outer #copyright li { float: left }` in place, and a box
   whose every child is floated has NO in-flow line box. `align-items: baseline`
   then has no baseline to read off the nav and falls back to its bottom margin
   edge, which aligns the bottom of the menu with the baseline of the copyright
   text — the menu rides visibly high, by roughly the descender depth, and no
   amount of tuning on the container fixes it because the container is not what
   is wrong. Unfloating the items restores a real first baseline.

   Flex on the <ul> rather than inline-block items, so the gap is declared once
   and there is no whitespace-between-inline-blocks to think about. */
#footer-outer #copyright .col .dfx-footer-legal ul {
	float: none;
	display: flex;
	flex-wrap: wrap;
	column-gap: 1.5rem;
	row-gap: 0.25rem;
}

/* The parent's `float: left; margin-left: 20px` is the gap between two social
   icons. Here the flex column-gap above owns the spacing, and leaving the margin
   would stack on top of it and read as a stray indent on the first item. */
#footer-outer #copyright .col .dfx-footer-legal li {
	float: none;
	margin-left: 0;
}

/* THE LANGUAGE SWITCHER'S FLAG, which lands in this menu as a WPML menu item and
   arrives carrying Salient's `.row .col img { margin-bottom: 15px }`. On a
   baseline-aligned inline image that margin lifts the flag 15px off the baseline
   and drags the label down with it, 14.5px below the links either side of it.

   Flex on the <a> and not `vertical-align: middle` on the image, for the same
   reason as the social icons above: middle seats at baseline plus half the
   x-height, which measured 0.96px low here. The <a> keeps its 24px line-height,
   so the li box is unchanged and the column's baseline still comes off the first
   item — which is a plain link as long as WPML's switcher stays last in the menu. */
#footer-outer #copyright .col .dfx-footer-legal .wpml-ls-menu-item > a {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
}

#footer-outer #copyright .col .dfx-footer-legal .wpml-ls-flag {
	margin: 0;
	flex: 0 0 auto;
}

/* COLOR AND HOVER MOVED OUT, to FOOTER LINK COLOR above. This section used to
   carry a Pewter rule and a hover rule scoped to `.dfx-footer-legal`, written when
   the legal menu was the only footer link Salient had painted too light — Steel
   Gray at 2.64:1 beside widget links at 9.31:1. Both are now covered by the
   footer-wide rule, so keeping copies here would mean two selectors deciding one
   color, and the narrower one silently winning.

   Nothing about the legal menu is special any more, which is the point: it was
   only ever different because Salient paints #copyright from a separate Theme
   Options field. It is a footer link and it gets the footer link treatment.

   WHAT THE OLD RULES KNEW, kept because it is still true of the region. Salient
   gives the copyright bar no text-link hover state at all — its only hover rules
   in there target `li a:hover i`, the social ICONS — so the underline on hover is
   this site's addition rather than an override of something. */

/* STACKED LAYOUT — NO MEDIA QUERY, AND THAT IS THE FIX RATHER THAN AN OMISSION.
   This section used to carry `margin-top: 0.75rem` on .dfx-footer-legal under a
   max-width: 690px query, for the point where Salient collapses the copyright
   columns to full width and the menu drops under the copyright line flush
   against it. That margin cannot survive the move to a flex column: the nav is
   now a flex item on the same line as the <p>, so a top margin applies whether
   or not it has wrapped, and at any width where both still fit it just shoves
   the menu off the shared baseline.

   `row-gap` on the container replaces it and is strictly better — it applies
   only when the items actually wrap, which is the real condition. 690px was
   always a proxy for "these two no longer fit side by side", and a proxy that
   the copyright text can falsify by getting longer. */


/* --- Tier ladder ------------------------------------------------------------- */
/* The same tiers the comparison table renders as columns, rendered as the pricing-page
   pattern: a card per tier, grouped into panels by rung. Markup and the reasoning behind
   the grouping are in template-parts/product/tier-ladder.php.

   OWNS NO CARD STYLING. The cards are .dfx-card--product — the same component as the
   archive grid and the tier table's headers — so the fill, radius, shadow, internal
   rhythm, text colors and button treatment all arrive with it. Everything below is
   either the panel layer, which the card knows nothing about, or the feature list, which
   no other surface renders.

   WHY PANELS AT ALL, since a row of cards would be less markup. The panel is what makes
   "these two are peers" visible: two cards inside one panel read as a choice at the same
   level, two panels read as a step up the ladder. That distinction is the whole point of
   the rung — without it, four cards in a row say nothing about which of them are
   alternatives and which are upgrades. */

.dfx-tier-ladder__panels {
	display: flex;
	flex-wrap: wrap;
	/* NARROWER THAN THE CARD GAP, WHICH READS AS WRONG AND IS NOT — THE PADDING DOES THE
	   SEPARATING NOW. This was 2.5rem under a rule that the space between two sections must
	   exceed the space between two tiers inside one, or the grouping inverts. That rule was
	   written when the panels had no surface: with nothing but gaps to go on, the larger gap
	   was the only thing saying which cards were peers.

	   The panels have a fill, a border and 2rem of padding since then, so measure what a
	   reader actually sees between the last card of one section and the first of the next:
	   32px of padding + 24px of gap + 32px of padding = 88px, against 32px between two cards
	   in the same panel. The boundary is drawn nearly three times over, and the extra 16px
	   was buying nothing except two boxes that looked like they had drifted apart.

	   Costs nothing in the row arithmetic — the cards are grid tracks in `1fr`, so the 16px
	   this returns is absorbed by the tracks and no basis needs re-checking. */
	gap: 1.5rem;
	/* Stretch, so a panel holding a short rung still reaches the height of the tallest
	   one beside it and the panels read as one band rather than as ragged boxes. */
	align-items: stretch;
	/* CENTERED, WHICH ONLY BECAME A QUESTION WHEN THE PANELS STOPPED FILLING THE ROW. While
	   each one grew to claim its share of the content column there was no slack to place, so
	   flex-start and center rendered identically. Now that a panel wraps its cards — see its
	   own rule — a two-tier ladder leaves several hundred pixels over, and left-aligning it
	   reads as a layout that failed to fill rather than a group sitting in its column.

	   ON THE GROUP, NOT INSIDE IT. This positions the panel boxes and nothing else: the
	   section heading and every card stay left-aligned against their own edges, which is what
	   keeps a tier a column of type rather than a centered poster.

	   Applies per line, so a ladder that wraps to a second row centers the remainder too —
	   correct for the same reason, and the case a fixed margin would get wrong. */
	justify-content: center;
}

/* THE PANEL WRAPS ITS CARDS RATHER THAN FILLING THE ROW. It was
   `flex: 1 1 calc( var(--dfx-panel-size) * 16rem )` — a basis tracking the card count, so a
   panel of two claimed twice the width of a panel of one and both then grew to consume the
   content column. That is why two tiers used to stretch to 470px each: nothing capped them,
   so the row's leftover space was theirs.

   `0 1 auto` MAKES THE CARDS DECIDE. The grid below states its own maximum, so the panel's
   content width is the capped grid plus padding, and a panel of one is now visibly narrower
   than a panel of two instead of merely starting that way. It can still SHRINK, which is what
   keeps a four-card row inside a narrow container.

   WHAT THIS RETIRES: the basis arithmetic that used to live here, and the warning that went
   with it. The old floor had to clear the space four cards actually got — 1345 − 24 − 128 − 64
   = 1129 / 4 = 282px against a 288px basis at one point, which silently wrapped the row in
   two. Nothing is calculated against the gap any more, so changing the padding or the gap
   cannot break the row shape. */
.dfx-tier-ladder__panel {
	flex: 0 1 auto;
	display: flex;
	flex-direction: column;
	/* 2rem, UP FROM 1.25rem, AND IT SPACES EXACTLY ONE THING. A section has two children —
	   the heading block and the row of tiers — so this gap is the whole of the distance
	   between the section label and the cards under it, and nothing else moves with it.
	   1.25rem was set when the heading was 20px and the cards had their own dark casing to
	   separate them from it. At 32px with the casing gone the label sat almost on top of the
	   first tier name, which reads as one heading stack rather than a label over a group. */
	gap: 2rem;
	/* 2rem, UP FROM 1rem, BECAUSE THE CARDS NO LONGER HAVE THEIR OWN. The tiers used to be
	   product cards with 2rem of padding each, so the panel only had to space the boxes;
	   now the panel is the only container and this is the whole inset. The reference is
	   about this roomy.
	   THE GAP IS A TOKEN because the sections and the cards inside them have to agree, and
	   because the section-padding sum in the comment above depends on it. It fed a flex
	   basis calculation too until the cards became grid tracks, which is one fewer place
	   for it to be stated. */
	--dfx-tier-ladder-gap: 2rem;
	/* THE CEILING ON A TIER, stated beside the gap because the row's max-width is computed
	   from both. Above roughly this width a tier stops reading as a column of type and starts
	   reading as a panel of its own, and the feature list — one short phrase per line — opens
	   up gaps at the end of every line. Below it nothing changes: the tracks are still 1fr and
	   still divide whatever the container gives them. */
	--dfx-tier-card-max: 350px;
	padding: 2rem;
	border-radius: var(--dfx-radius-raised);
	/* THE FALLBACK IS THE DEFAULT, WHICH IS WHY THE ELEMENT WRITES A PROPERTY RATHER THAN A
	   COLOR. --dfx-panel-bg and --dfx-panel-border arrive on the element's style attribute
	   only when an editor has picked something, so an unset section still follows
	   brand-tokens.css and a later token change reaches every ladder nobody has overridden.
	   Setting `background-color` directly from the element would have made every override
	   permanent and invisible to the stylesheet. */
	background-color: var(--dfx-panel-bg, var(--dfx-color-surface-raised));
	border: 1px solid var(--dfx-panel-border, var(--dfx-color-border-subtle));
	/* THE SURFACE SETS THE SECONDARY BUTTON'S FILL, because a pale fill only reads as a
	   button while the surface under it is a different color. This panel is the default
	   white, so the blue tint is safe here; the tinted variants below flip it to white.
	   Declared on the panel rather than the button so the two colors are decided in the
	   same place as the surface they depend on. */
	--dfx-tier-cta-fill: #EEF7FF;
	--dfx-tier-cta-fill-hover: #C7E3FF;
}

/* THE SURFACE IS UNCONDITIONAL, and the rule that used to make it conditional is gone.
   A `--open` variant stripped the fill, border and padding whenever the element had no
   sections, on the reasoning that a box around an ungrouped ladder asserts a grouping
   nobody asked for. The cost was that the same component looked like two different things
   depending on how one instance happened to be configured: a bordered panel on the
   packages page, bare cards on a product page. Consistency wins — the ladder is one
   component and reads the same wherever it is placed. The template no longer emits the
   class.

   EVERY SECTION ABOVE THE FIRST IS TINTED, and the tint is derived from the brand rather
   than picked, so it cannot drift from the palette. This is the reference's highlighted
   panel, doing one job: saying which end of the ladder is the fuller offer. It is a
   background change only — no border color, no shadow, nothing that would make the
   panel itself look like a card sitting on the page.

   NOT "the recommended tier". A recommendation is a commercial decision about one tier,
   which nothing in the content model records yet; this says something weaker and already
   true from the data, which is that these tiers sit higher on the ladder. */
.dfx-tier-ladder__panel--upper {
	/* Same two properties, different defaults — so an editor's color still wins here, and
	   leaving both blank gives the reference's pairing: a bordered white box beside a
	   filled tinted one. */
	background-color: var(--dfx-panel-bg, color-mix( in srgb, var(--dfx-color-brand) 7%, var(--dfx-color-surface-raised) ) );
	border-color: var(--dfx-panel-border, transparent);
	/* WHITE HERE, because the blue tint against this panel's 7% brand wash (#F0F3F6) is
	   1.03:1 and all but vanishes. White is 1.11:1 — still faint, but the strongest edge
	   available without a border. If an editor colors the panel darker it only improves. */
	--dfx-tier-cta-fill: var(--dfx-color-surface-raised);
	--dfx-tier-cta-fill-hover: var(--dfx-color-border-subtle);
}

/* THE SECTION LABEL: heading, and an optional line under it. Wrapped in a __panel-head so
   the pair sits at one of the panel's flex gaps rather than two — a heading and its own
   subheading are one block, and spacing them like siblings of the card row put as much
   space between the heading and its subheading as between the subheading and the cards.

   Salient's `p { padding-bottom: 1.5em }` is why both rules zero padding as well as
   margin: it lands on a bare paragraph at 0-0-1, so a margin reset alone leaves 24px of
   padding under text that measures as having none. Same trap the card body documents. */
.dfx-tier-ladder__panel-head {
	display: flex;
	flex-direction: column;
	/* 0.5rem, up from 0.35rem: the heading takes the h2 step — 32px today — and a gap
	   tuned under a 20px line reads as crowding under a heading three times that. */
	gap: 0.5rem;
}

.dfx-tier-ladder__panel-heading,
.dfx-tier-ladder__panel-subheading {
	margin: 0;
	padding: 0;
}

/* Sized down and muted, so it reads as support for the heading rather than as a second
   heading. Pewter is the token that stays readable on both the raised white of a section
   and the tint of an upper one — Soft Stone is a border color and fails on white. */
.dfx-tier-ladder__panel-subheading {
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-ui);
	color: var(--dfx-color-text-muted);
}

/* A GRID WITH subgrid ROWS, WHICH IS WHAT LINES THE BUTTONS UP. Each card contributes
   three rows — head, CTA, feature list — and takes their heights from the tallest card in
   the row, so a three-line audience line no longer pushes its own button 18px below its
   neighbour's. As a flex row every card was a stack whose contents landed wherever the
   elements above them ended.

   `grid-template-rows` IS DECLARED HERE AND INHERITED THERE. A card sets
   `grid-template-rows: subgrid`, which only means anything if the parent has rows to
   share — hence the three `auto`s. The third is the list, which takes the remaining space
   so a short card's panel does not stretch its list.

   `repeat(var(--dfx-row-size), 1fr)` REPLACES flex-basis ARITHMETIC. Four cards per row
   is now the column count rather than a width calculated against the gap, which is both
   simpler and exact — no rounding, and nothing to keep in sync with the gap. A fifth card
   wraps onto a new row of the same tracks and keeps its width, which is what the
   flex-grow: 0 note below was solving by hand.

   WHERE THIS STOPS: cards in DIFFERENT sections. Each section is its own grid container,
   so alignment is guaranteed within a section and only approximate across two — the
   sections have equal padding and heading blocks, so in practice the rows line up unless
   the audience lines differ in length. Aligning across sections would mean one grid
   spanning the panels, which is exactly the boxes the sections exist to draw. */
.dfx-tier-ladder__cards {
	display: grid;
	grid-template-columns: repeat( var(--dfx-row-size, 1), minmax( 0, 1fr ) );
	grid-template-rows: auto auto 1fr;
	gap: var(--dfx-tier-ladder-gap, 1.5rem);
	/* A CAP ON THE ROW, NOT ON THE CARD, and that distinction is the whole reason this works.
	   `max-width` on the card itself would leave the 1fr track wider than what sits in it —
	   the cards would hold 350px and the gaps between them would grow to absorb the slack, so
	   a row of two would read as two columns adrift rather than as a pair. Capping the GRID
	   keeps the tracks equal to the cards, and the leftover space ends up outside the panel
	   where the panel's own `flex: 0 1 auto` gives it back to the page.

	   The tracks stay `1fr`, so below the cap they still divide the container equally and a
	   narrow screen shrinks them rather than overflowing. 350px is a ceiling, not a width.

	   The gap has to appear here because n cards have n−1 gaps between them; it reads from the
	   same token the grid uses, so the two cannot disagree. */
	max-width: calc(
		( var(--dfx-row-size, 1) * var(--dfx-tier-card-max, 350px) )
		+ ( ( var(--dfx-row-size, 1) - 1 ) * var(--dfx-tier-ladder-gap, 1.5rem) )
	);
	/* Fills the panel so cards in a short rung still reach the bottom of a taller
	   neighbouring panel — the panel stretches, and without this the card would sit at
	   the top of the space it was given. */
	flex: 1 1 auto;
	align-items: stretch;
}

/* --- The tier itself: a column, not a card ------------------------------------- */
/* NO FILL, NO BORDER, NO SHADOW, NO RADIUS, and this replaces .dfx-card--product. The
   ladder used to render the product card component, which put a box inside a box: the
   section panel draws a group boundary, and four dark tiles inside it drew four more. The
   reference has no casing on a plan at all — the panel is the only container and the tiers
   are columns of type within it.

   WHAT THE CARD WAS ALSO DOING WAS SETTING COLORS, so this section has to. It carried a
   dark fill and a light `color`, plus an entry in brand-base.css's list of contexts that
   flip --dfx-heading-ink to currentColor. Without it the tier name goes back to the
   page's heading color and the body copy to the page's text color, which is correct on a
   white or faintly tinted panel — and is why the tick, note, marker and editor-note
   colors below all changed at the same time. Anything still reading as light-on-dark is a
   leftover from that component, not a deliberate choice.

   The rhythm that .dfx-card__body used to provide is restated on __card-body, because that
   was doing real work: a flex column with one gap, and margin AND padding zeroed on the
   children because Salient puts 1.5em of PADDING under a bare paragraph. */
/* `display: contents`, SO THE WRAPPER DOES NOT BREAK THE SUBGRID. The three cells have to
   be grid items of the CARD to take its rows, and a wrapping div would make them items of
   itself instead — one cell holding a stack, which is the flex layout this replaces. The
   element stays because it is what the markup nests, and contents removes it from layout
   without removing it from the DOM. */
.dfx-tier-ladder__card-body {
	display: contents;
}

.dfx-tier-ladder__card-body > * {
	margin: 0;
	padding: 0;
}

/* The tier name. Size from the utility in the markup; this only removes the heading margins
   Salient supplies, since the flex gap above is what spaces the stack now. */
.dfx-tier-ladder__card-title {
	margin: 0;
	padding: 0;
}

/* A CHIP INSIDE THE TIER NAME — featured, or a coming-soon badge, or both. The heading is
   24px and the chip's own type is 11px, so it needs pulling off the cap height to sit on
   the name's optical center rather than its baseline; and the shared badge margin has to
   go, for the same reason it does in the feature list. */
.dfx-tier-ladder__card-title .dfx-badge {
	margin: 0 0 0 0.5rem;
	padding: 0.1rem 0.55rem;
	vertical-align: 0.15em;
}

/* Who the tier is for. Muted rather than Soft Stone, which was the dark card's value and
   is a border color on white — Pewter is the token that stays readable on both a white
   panel and a tinted one. */
.dfx-tier-ladder__built-for {
	color: var(--dfx-color-text-muted);
}

/* --- Row and column arithmetic ------------------------------------------------- */
/* CAPPED AT FOUR PER ROW, and the cap is now a column count rather than a flex basis:
   --dfx-row-size is min(cards, 4) from the markup and becomes the number of grid tracks.
   Four cards is what fits the content column and about as much as a reader compares at a
   glance, so a section of five wraps onto a second row of the same tracks.

   WHAT THIS REPLACED, since the history is instructive: a flex basis of
   `(100% - (n - 1) * gap) / n` with flex-grow: 0. It worked, but it recomputed by hand
   what a grid already knows, and it had a failure mode — with grow left at 1 a wrapped
   fifth card stretched to fill its line, rendering four at 324px and a fifth at 1343px.
   Grid tracks make that impossible rather than avoided. */
.dfx-tier-ladder__card {
	display: grid;
	/* Spans the three rows the container declares and adopts them as its own, which is the
	   whole of the alignment: same head height, same CTA row, same list start, decided by
	   the tallest card in the row rather than by each card's own contents. */
	grid-row: span 3;
	grid-template-rows: subgrid;
	min-width: 0;
}

/* TWO ROWS WHEN THE ELEMENT'S CARD BUTTON IS SET TO "None", AND BOTH HALVES ARE REQUIRED.
   The subgrid above is an exact contract: the panel declares three rows and each card
   claims three. Drop the button markup and the row is still declared, so every card keeps
   a `1fr` band of nothing where the buttons were — and because that row is the flexible
   one, it absorbs the panel's leftover height and the gap can run to a hundred pixels.

   The span and the template have to change together. Changing only `grid-template-rows`
   leaves the cards spanning three rows into a two-row grid, which creates an implicit
   third; changing only the span leaves a declared row with nothing in it. */
.dfx-tier-ladder--no-cta .dfx-tier-ladder__cards {
	grid-template-rows: auto 1fr;
}

.dfx-tier-ladder--no-cta .dfx-tier-ladder__card {
	grid-row: span 2;
}

/* The card's three cells. __head keeps the internal flex rhythm — title, price line and
   audience line are read as a block and do not need aligning individually — while the CTA
   and the list are cells of their own so they can be pinned across the row.

   THE HEAD IS ONE CELL RATHER THAN THREE ON PURPOSE. Five subgrid rows would align the
   title, the price line and the audience line separately, which sounds tidier and lines up
   things nobody compares; what a reader compares is where the buttons and the lists
   start. */
.dfx-tier-ladder__head {
	display: flex;
	flex-direction: column;
	gap: 0.625rem;
}

.dfx-tier-ladder__head > * {
	margin: 0;
	padding: 0;
}

/* What stands in place of a price. Sits directly under the tier name in the slot the
   reference gives to "$10 per member / month" — see the template part for why there is no
   number in it. Full text color rather than muted: it is the second thing read on a tier,
   and the emphasis weight alone was not enough to hold it once the dark fill went. */
.dfx-tier-ladder__pricing {
	font-weight: var(--dfx-weight-emphasis);
}

/* The CTA's wrapper, which exists for a reason that is not layout — see the template
   part. A little more room above and below than the card's own 0.625rem gap, because
   this is the divide between what the tier IS and what it CONTAINS. */
.dfx-tier-ladder__cta {
	/* NEGATIVE, AND ONLY UPWARDS. The CTA is a subgrid cell, so the space around it is the
	   grid's 2rem row gap plus whatever margin the cell carries — 40px above and 40px
	   below at 0.5rem each. Pulling 0.75rem off the top leaves 20px above the button and
	   40px below, which is the asymmetry the card wants: the button belongs to the tier
	   name and price above it, not to the feature list below.
	   DONE HERE RATHER THAN ON THE GRID'S row-gap, which is the other way to close the
	   space and would also tighten the stacked cards on a phone and any row that wraps —
	   the row gap is shared by every card block, this margin is the cell's own. */
	margin-top: -0.75rem;
	margin-bottom: 0.5rem;
}

/* A LINK NEEDS LESS ROOM THAN A PILL, AND THE OFFSET ABOVE WAS TUNED FOR A PILL. The
   button is a 50px box whose own padding does half the separating; the arrow link is one
   line of 14px text, so the same -0.75rem leaves it floating between the audience line and
   the list with no visible relationship to either. Pulling harder puts it where the
   button's top edge was, which is where the eye expects the next thing after the price
   block to start. */
.dfx-tier-ladder__cta--link {
	margin-top: -1.25rem;
	margin-bottom: 0.25rem;
}

/* BALTIC, NOT BRASS, WHICH IS THE ONE THING THAT CANNOT BE COPIED FROM .dfx-card__cta.
   That link is the same control on the product cards, and it is Brass — legible at 6.78:1
   only because the card behind it is Obsidian. The ladder's cards have no casing, so this
   link sits on the panel's white or its faint brand wash, where Brass is 2.29:1 and fails.
   Baltic is 8.46:1 on white and 8.1:1 on the tint.

   THE SELECTOR IS FOUR CLASSES BECAUSE OF ONE Salient DECLARATION, and a plain
   `.dfx-tier-ladder__compare` at 0-1-0 lost to it silently — the link rendered in body ink
   and looked like the color had simply not been written. The rule is:

     .nectar-cta .link_wrap .link_text { color: inherit }        0-3-0

   dfx_link_with_arrow() puts `link_text` on the anchor alongside our class, so that
   `inherit` matches every arrow link on the site and beats any single-class color on the
   same element. Inheriting from the card body is how it came out #424752.

   Worth knowing beyond this rule: `.dfx-feature-link` sets its color at 0-1-0 and is
   subject to exactly the same defeat. Not touched here — it is a separate component with
   its own contrast argument — but it is the next thing to check if a feature link ever
   reads as body text.

   Size and weight are stated here rather than inherited, because the shared `.dfx-card__cta`
   rules set them for a card footer and this cell is not one. The arrow's structure and
   motion still come from the Link arrow block near the top of this file. */
.dfx-tier-ladder__cta .nectar-cta .link_wrap .dfx-tier-ladder__compare {
	color: var(--dfx-baltic);
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-emphasis);
}

/* Obsidian at 15.5:1 — up from Baltic's 8.46, so the hover is a step toward the reader
   rather than away. The card link goes to Signal White for the same reason on a dark
   surface; this is that rule inverted for a light one. */
.dfx-tier-ladder__cta .nectar-cta .link_wrap .dfx-tier-ladder__compare:hover,
.dfx-tier-ladder__cta .nectar-cta .link_wrap .dfx-tier-ladder__compare:focus {
	color: var(--dfx-obsidian);
}

/* THREE STEPS OF EMPHASIS: solid Obsidian on the featured tier, a pale Info fill on the
   rest, and Brass wherever a button sits on a dark surface — nowhere in the ladder, every
   tier card in the comparison table.

   A PALE FILL RATHER THAN AN OUTLINE, replacing the outline this rule used to draw. The
   fill is 1.08:1 against a white section, so the shape is carried by the label (15.48:1)
   and not by the pill — the trade accepted knowingly. Blue-50/blue-100 literals from the
   SUI ramp, as .dfx-badge--add-on does: the marketing palette has no step this light.

   THE COLOR COMES FROM THE PANEL, not from here, because a pale fill depends entirely on
   what is behind it: blue-50 on the upper panel's brand wash is 1.03:1 and disappears. The
   panel rules set --dfx-tier-cta-fill to the tint on any light surface and to white on the
   upper panel. The fallback repeats the tint for a button rendered outside a panel.

   0-3-1, above the 0-2-0 rule below that fills the button from the CTA token, so the
   featured card — which does not match `:not()` — keeps the solid fill it inherits.

   HOVER DARKENS ONE STEP IN THE SAME RAMP rather than filling in with Obsidian, per the
   palette rule on interaction states; the Obsidian label holds across both. */
.dfx-tier-ladder__card:not(.dfx-tier-ladder__card--featured) .dfx-tier-ladder__cta .dfx-card__cta-button {
	background-color: var(--dfx-tier-cta-fill, #EEF7FF);
	/* TRANSPARENT, NOT ZERO. brand-base gives every non-see-through .nectar-button a 1px
	   transparent border, so `border: 0` here would render these three 2px shorter than
	   the featured tier's solid pill beside them. */
	border: 1px solid transparent;
	color: var(--dfx-color-cta);
}

.dfx-tier-ladder__card:not(.dfx-tier-ladder__card--featured) .dfx-tier-ladder__cta .dfx-card__cta-button:hover,
.dfx-tier-ladder__card:not(.dfx-tier-ladder__card--featured) .dfx-tier-ladder__cta .dfx-card__cta-button:focus {
	background-color: var(--dfx-tier-cta-fill-hover, #C7E3FF);
	color: var(--dfx-color-cta);
}

/* Salient swaps the label color from script on hover — see the note in brand-base.css —
   so the span is targeted directly here too, or the label goes white on the pale fill the
   moment the script runs. */
.dfx-tier-ladder__card:not(.dfx-tier-ladder__card--featured) .dfx-tier-ladder__cta .dfx-card__cta-button span {
	color: inherit;
}

.dfx-tier-ladder__cta .dfx-card__cta-button {
	/* Full width, as in the comparison table's cards and for the same reason: one button
	   at its natural width leaves dead space beside it in a column this narrow, and a
	   full-width button is the convention for a plan card. `display: block` is needed as
	   well as the width — Salient's .nectar-button is inline-block, which takes its width
	   from its content unless told otherwise. */
	display: block;
	width: 100%;
	text-align: center;
}

/* "Everything in Core, and:" — the line the whole component is built around. Emphasis
   weight rather than a heading element or size: it labels the list beneath it, and a
   heading here would compete with the tier name three lines above. */
.dfx-tier-ladder__lead {
	font-weight: var(--dfx-weight-emphasis);
	/* 12px, down from the 21px Salient's global `p` gives it via
	   --nectar-paragraph-bottom-spacing (1.5em of 14px). It labels the list directly
	   beneath it, so it should sit closer to it than to the button above. */
	padding-bottom: 0.75rem;
	/* Heading ink rather than the body color it was inheriting — this is a label, and
	   the step up in weight was doing that job alone. */
	color: var(--dfx-heading-ink);
}

.dfx-tier-ladder__features,
.dfx-tier-ladder__offers {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	/* THE DENSEST TEXT ON THE SITE, and the element the "our type feels too big" report
	   came from. Was 0.95rem/15.2px with no leading of its own, so it inherited body's
	   1.6 — a prose leading on 48 three-word list items sitting in a card column. Now
	   14px/1.45, which is where Notion's pricing cards sit. Both halves matter: the size
	   is 8% and the leading another 9%, and taking only the size banks about half of it. */
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-ui);
}

/* A TWO-COLUMN GRID, NOT FLEX, so every row's text starts at the same x whether or not
   it has a tick. Flex sizes the first child to its content, which was fine while that
   child was always a 17px tick and wrong the moment an add-on row put a word there
   instead — the list ended up with two left edges. A fixed first track fixes the
   position for every row, and the marker moved to the end of the label; see the template
   part.

   `align-items: start` keeps the tick on the first line rather than centring it against
   a row that wraps to two, and the label column wrapping under itself is what the grid
   buys over a text-indent. */
.dfx-tier-ladder__features li {
	display: grid;
	grid-template-columns: 1.1rem 1fr;
	align-items: start;
	gap: 0.5rem;
}

/* BLOCK, AND THIS IS LOAD-BEARING. The conditional note inside it is display: block, and
   a block inside an inline box makes the browser split that box around it — which left
   an empty line box under every row carrying a note and rendered those items 69px tall
   next to their neighbours' 24px. It read as a margin nobody had set. */
.dfx-tier-ladder__label {
	display: block;
}

/* Salient bundles Font Awesome 4.7.1, hence `fa fa-check` and not the `fas` prefix of
   FA5+. The tick is aria-hidden in the markup: the list item's text is the content, and
   a text equivalent per row would make a screen reader read "check Mobile Check-in"
   twelve times. Same color as the comparison table's ticks, so a tick means the same
   thing on both surfaces. */
.dfx-tier-ladder__tick {
	color: var(--dfx-success);
	font-size: 0.9rem;
	/* Nudged onto the text's optical line. The glyph's box is taller than its ink, so
	   flex-start alone leaves it sitting high against the first line. */
	margin-top: 0.2em;
	line-height: 1;
}

/* ADD-ONS AND COMING-SOON GET A CHIP, NOT A TICK, because a tick means "you get this" and
   neither of them does. They are .dfx-badge variants now rather than a bespoke marker —
   the same component the product card and the comparison table use — so the word "Add-on"
   looks identical everywhere it appears. What is left here is the two things a chip needs
   INSIDE a feature list.

   SMALLER THAN A STANDALONE BADGE. The component is sized for a card title or a table
   cell; at 0.25rem/0.875rem it dominates a 0.95rem list row. The padding and size come
   down, the pill shape and the colors do not.

   MARGINS ZEROED because the shared rule carries `margin: 0 0 0.5rem` for the stacked
   contexts it was written for, and here it would only make the row taller than its text. */
/* WHAT THE TIER SELLS ALONGSIDE ITSELF, deliberately outside the ticked list — see
   tier-ladder.php for why the card stopped printing add-ons as bullets. No tick column,
   because a tick is the mark for "included" and the badge beside it says the opposite;
   and a divider, because two lists with no boundary read as one list whose last rows are
   styled oddly. */
.dfx-tier-ladder__offers {
	margin-top: 0.75rem;
	padding-top: 0.75rem;
	border-top: 1px solid var(--dfx-color-border-subtle);
}

/* FLEX SO THE MARKUP'S WHITESPACE STOPS COUNTING. index-item.php and card.php both close
   the gap by emitting no whitespace before the chip, because the chip's own left margin is
   meant to be the whole gap and a text node doubles it. A flex container drops
   whitespace-only children instead, which gets the same result without the template having
   to be written on one line — and it keeps holding if someone reformats it. */
.dfx-tier-ladder__offer {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
}

/* INLINE, unlike `.dfx-tier-ladder__label` directly above, which is `display: block` for
   a conditional note that no longer renders. Reusing that class here would put the badge
   on its own line under the name. */
.dfx-tier-ladder__offer-name {
	font-weight: 500;
}

.dfx-tier-ladder__features .dfx-badge,
.dfx-tier-ladder__offers .dfx-badge {
	/* Left margin only: the gap to the feature name it qualifies. The shared rule carries
	   `margin: 0 0 0.5rem` for the stacked contexts it was written for, which here would
	   only make the row taller than its text. */
	margin: 0 0 0 0.4rem;
	/* Tighter than a standalone chip, which is sized for a card title or a table cell and
	   dominates a 0.95rem list row at 0.25rem/0.875rem. Padding only — the type, the pill
	   and the colors stay the component's. */
	padding: 0.05rem 0.5rem;
	/* NO text-transform AND NO letter-spacing, AND THAT WAS A CORRECTION. This rule
	   uppercased "Add-on" to ADD-ON, which made the ladder's chip a different object from
	   the identical chip in the comparison table and on the product card — same word, same
	   meaning, two voices, which is the thing this change set out to fix. The component
	   deliberately sets no text-transform so a label renders as it is written; overriding
	   that here was reintroducing the inconsistency one component down. */
	white-space: nowrap;
	vertical-align: 0.05em;
}

/* `.dfx-tier-ladder__note` IS GONE, not moved. The card no longer prints eligibility
   caveats at all — they are numbered markers in the comparison table and a list beneath
   it, so the same condition is stated once per page instead of once per surface. The
   `display: block` on `.dfx-tier-ladder__label` above was written for this note; it stays
   because the flex row still wants a single block text child. */

/* EDITORS ONLY, and it has to be visible enough to be acted on — this is what a
   suppressed cumulative heading looks like from the front end, and without it the
   difference between "Everything in Core, and:" and "Includes:" on the card beside it
   reads as a styling inconsistency rather than as a content problem. Brass on the dark
   card, which is the theme's attention color, at a size that says "not for visitors". */
.dfx-tier-ladder__editor-note {
	margin-top: 0.5rem;
	padding-top: 0.5rem;
	/* A light-on-dark divider and a Brass note were both readable on the card that used to
	   be here and are not on a white panel. The subtle border token and the muted text
	   color are the light-surface equivalents. */
	border-top: 1px solid var(--dfx-color-border-subtle);
	font-size: var(--dfx-size-micro);
	font-style: italic;
	color: var(--dfx-color-text-muted);
}

/* ONE CARD PER ROW BELOW THE DESKTOP THRESHOLD, overriding the row arithmetic above
   rather than adjusting it. A quarter of a 700px line is 165px, which is narrower than the
   floor a card's built-for copy needs, and two cards abreast on a phone is worse than
   scrolling a column of four. The panels themselves already wrap on their own basis, so
   this only has to handle the inside of one. */
@media (max-width: 999px) {

	/* ONE CARD PER ROW BELOW THE DESKTOP THRESHOLD, by collapsing the tracks rather than
	   overriding a width. A quarter of a 700px line is 165px, narrower than the floor a
	   card's audience line needs, and two abreast on a phone is worse than scrolling a
	   column of four.
	   The subgrid still applies, which is the point of doing it this way: each card is one
	   column and three rows, so the head/CTA/list alignment holds down the column instead
	   of being switched off on the layout that needs it least. */
	.dfx-tier-ladder__cards {
		grid-template-columns: minmax( 0, 1fr );
	}
}

/* EDITORS ONLY — a Tier Ladder element that cannot resolve a product, or one pointed at
   a product with fewer than two tiers. Styled enough to be noticed on a page an editor
   is reviewing, and gated in PHP so a visitor never sees it. Brass because that is the
   theme's attention color, and a dashed rule rather than a filled panel because this is
   scaffolding, not content. */
.dfx-tier-ladder__setup-note {
	margin: 0;
	padding: 1rem 1.25rem;
	border: 1px dashed var(--dfx-brass);
	border-radius: var(--dfx-radius-raised);
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	font-style: italic;
	color: var(--dfx-color-text-muted);
}

/* ============================================================================
   ACCORDION TITLES — the visible size lives on the link, not the heading
   ============================================================================

   The heading tag is only a box: Salient renders the label inside an `<a>` and
   sizes that anchor at 14px/16px, so `h3.toggle-title` computes 24px from the
   scale while the words on screen stay 14px. The size step here is the same one
   the pairing table gives a list-item title, and tracking follows the size down
   to the h4/h5 band rather than keeping h3's tighter value.

   Both selectors carry the size so the box and the link agree, and the anchor is
   escalated past Salient's own `div[data-style="minimal"]` rule — which sets 20px
   under 690px and is why these currently read larger on a phone than on desktop.

   Inline Small is excluded on purpose: 14px is that style's design, not this bug.

   `.dfx-faqs` IS LISTED BESIDE `.container-wrap`, and it is not belt-and-braces.
   `.container-wrap` only wraps builder content, and single-dfx_product.php renders its
   derived bands OUTSIDE that wrapper as full-bleed sections — so on every product page
   this rule matched nothing and the questions fell back to element-toggles.css at 14px.
   That is the same reason /company/privacy looked right: its accordion is page content,
   so it was inside the wrapper all along. `.dfx-faqs` is the div this element always
   emits, which catches it wherever the band ends up. Both selectors are kept at the
   same weight so neither changes which of the two wins.

   `.dfx-feature-list` CAME OFF THIS LIST. That section's category accordions are static
   labels over a checklist now — see feature-list.php — so it emits no `.toggles` at all and
   the two selectors matched nothing. */
html body .container-wrap .toggles:not([data-style="minimal_small"]) .toggle > .toggle-title,
html body .container-wrap .toggles:not([data-style="minimal_small"]) .toggle > .toggle-title a,
html body .dfx-faqs .toggles:not([data-style="minimal_small"]) .toggle > .toggle-title,
html body .dfx-faqs .toggles:not([data-style="minimal_small"]) .toggle > .toggle-title a {
	font-size: var(--dfx-size-h5);                            /* 18px */
	line-height: var(--dfx-line-height-heading-small);        /* 1.4 */
	letter-spacing: var(--dfx-letter-spacing-heading-small);  /* -0.01em */
}

/* THE ANSWER COPY TAKES THE READING MEASURE WHEREVER THE BAND LANDS, and this is the
   same bug as the titles above, one property later. brand-base.css caps prose at 66ch
   with `.container-wrap p` / `.container-wrap li`, so a FAQ inside builder content is
   measured — /packages, /company/privacy — while the derived band on every product page
   is a full-bleed section OUTSIDE that wrapper and ran the full 1231px container.

   `.dfx-faqs` is the div the element always emits, so scoping to it catches the band
   wherever it renders. 66ch is brand-base's figure, restated rather than derived: if the
   reading measure moves, it moves in both places.

   ONLY THE ANSWER, and only inside `.inner-toggle-wrap`. The question is a component
   heading and is exempted from the heading measure on purpose — see the readability
   section in brand-base.css, where a toggle title wrapped at 36ch took its click target
   with it. */
.dfx-faqs .inner-toggle-wrap p,
.dfx-faqs .inner-toggle-wrap li {
	max-width: 66ch;
}

/* ============================================================================
   OEM GRID — [dfx_oem_grid]
   ============================================================================

   The one-color treatments are filters over the single transparent asset:
   brightness(0) flattens every opaque pixel to black and preserves alpha, and
   invert(1) after it gives white. A mark exported onto an opaque box becomes a
   solid rectangle — the asset's fault, and what the checkerboard preview on the
   term screen exists to catch. */

/* Three height caps rather than one. Capped on height alone, a wide wordmark hits
   its cell's width limit and lands under the cap while a square badge sits at the
   full height — 33px against 64px at six columns. Oem_Meta::logo_shape() picks the
   bucket from the file's intrinsic ratio; the box height below stays constant so the
   marks still share a center line. Tune here, not per rule. */
.dfx-oem-grid {
	--dfx-oem-box: 64px;
	--dfx-oem-h-square: 40px;
	--dfx-oem-h-mid: 52px;
	--dfx-oem-h-wide: 64px;
	/* Column gap is a variable because the item width is calculated from it below.
	   3.5rem, matched to the integrations wall rather than tuned separately: two logo
	   walls can appear on one page and a different gutter on each reads as a mistake.
	   Was 5rem, which starved the cells at seven and eight across. */
	--dfx-oem-gap: 3.5rem;
	--dfx-oem-gap-row: 3.5rem;
}

.dfx-oem-grid__title {
	margin: 0 0 2rem;
	font-size: var(--dfx-size-h2);
	line-height: var(--dfx-line-height-heading);
	letter-spacing: var(--dfx-letter-spacing-heading);
	text-align: center;
}

/* Flex wrap rather than grid, so a short last row centers. CSS Grid cannot do that:
   with `1fr` tracks the columns fill the row whether or not items occupy them, so
   seven logos in four columns leave the trailing three hard against the left edge and
   justify-content has nothing to distribute. Widths still come out equal because the
   basis below is calculated, so this keeps the even columns and gains the centring. */
.dfx-oem-grid__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	column-gap: var(--dfx-oem-gap);
	row-gap: var(--dfx-oem-gap-row);
	/* flex-start, not center: on the cards layout a two-line manufacturer name makes
	   its item taller, and centring the ITEM would then drop that logo below the
	   others. Alignment of the marks themselves comes from the fixed-height box. */
	align-items: flex-start;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dfx-oem-grid--cols-2 .dfx-oem-grid__list { --dfx-oem-cols: 2; }
.dfx-oem-grid--cols-3 .dfx-oem-grid__list { --dfx-oem-cols: 3; }
.dfx-oem-grid--cols-4 .dfx-oem-grid__list { --dfx-oem-cols: 4; }
.dfx-oem-grid--cols-5 .dfx-oem-grid__list { --dfx-oem-cols: 5; }
.dfx-oem-grid--cols-6 .dfx-oem-grid__list { --dfx-oem-cols: 6; }
.dfx-oem-grid--cols-7 .dfx-oem-grid__list { --dfx-oem-cols: 7; }
.dfx-oem-grid--cols-8 .dfx-oem-grid__list { --dfx-oem-cols: 8; }

/* NO PER-COUNT GUTTER TIGHTEN HERE, unlike the integrations block at nine and ten. It
   was tried at seven and eight — 2rem, taking the logo box to 105.5px — and read big
   and clunky, because half this set is badges that then climb to their height caps
   while the wordmarks stay short. The base gutter came down to 3.5rem instead, which
   is the whole adjustment. If a mark is too small here the lever is fewer columns. */

/* The flex equivalent of a 1fr track: the row's width less its gaps, divided by the
   column count. The 0.02px comes off to absorb sub-pixel rounding — without it a full
   row can total a fraction over 100% and wrap its last item onto a line of its own. */
.dfx-oem-grid__item {
	flex: 0 0 calc(
		(100% - (var(--dfx-oem-cols, 4) - 1) * var(--dfx-oem-gap))
		/ var(--dfx-oem-cols, 4) - 0.02px
	);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.75rem;
	margin: 0;
	max-width: 100%;
}

/* Fixed height, so every logo box in a row is the same size and each mark centers
   inside its own. That is what puts a tall square badge and a wide horizontal lockup
   on one shared center line even though their caps differ. */
.dfx-oem-grid__logo {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: var(--dfx-oem-box);
}

/* Height is the constraint, not width — constraining width lets a tall square mark
   tower over a wide horizontal one. The default is the wide cap, which is also what
   an unbucketed logo gets. */
.dfx-oem-grid__logo img {
	display: block;
	width: auto;
	max-width: 100%;
	height: auto;
	max-height: var(--dfx-oem-h-wide);
	opacity: var(--dfx-oem-alpha, 1);
}

.dfx-oem-grid__logo--square img { max-height: var(--dfx-oem-h-square); }
.dfx-oem-grid__logo--mid img { max-height: var(--dfx-oem-h-mid); }
.dfx-oem-grid__logo--wide img { max-height: var(--dfx-oem-h-wide); }

.dfx-oem-grid--white .dfx-oem-grid__logo img { filter: brightness(0) invert(1); }
.dfx-oem-grid--black .dfx-oem-grid__logo img { filter: brightness(0); }
.dfx-oem-grid--grayscale .dfx-oem-grid__logo img { filter: grayscale(1); }

/* Inherits the band's color rather than taking the muted token, because the White
   treatment implies a dark band and a fixed gray would be unreadable on one. */
.dfx-oem-grid__name {
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	color: inherit;
	opacity: 0.75;
	text-align: center;
}

.dfx-oem-grid__note {
	margin: 0;
	padding: 1rem 1.25rem;
	border: 1px dashed var(--dfx-brass);
	border-radius: var(--dfx-radius-raised);
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	font-style: italic;
	color: var(--dfx-color-text-muted);
}

/* --- Carousel: the single scrolling row ------------------------------------------

   A CSS marquee, no JavaScript. PHP emits the logo set enough times to make two
   identical halves of the track, so translating the track -50% lands the second half
   exactly where the first started and the loop has no seam. `--dfx-oem-count` is the
   number of logos in ONE half; PHP sets it inline.

   Seconds PER LOGO rather than per lap: multiplying by the count means adding a
   manufacturer lengthens the lap instead of speeding the row up to keep it. */
.dfx-oem-grid--carousel {
	--dfx-oem-marquee-step: 6s;
	/* How far the fade at each edge reaches, so marks enter and leave rather than
	   being sliced by a hard overflow edge. */
	--dfx-oem-fade: 8%;
}

.dfx-oem-grid--speed-slow { --dfx-oem-marquee-step: 6s; }
.dfx-oem-grid--speed-medium { --dfx-oem-marquee-step: 3.5s; }
.dfx-oem-grid--speed-fast { --dfx-oem-marquee-step: 2s; }

/* `container-type: inline-size` is load-bearing, not a nicety. The track is
   `max-content` wide, so a percentage on an item would resolve against the TRACK and
   every item would be a percentage of a width it is itself setting. `cqw` below
   resolves against this element instead, which is the width actually in view. */
.dfx-oem-grid__viewport {
	container-type: inline-size;
	overflow: hidden;
	/* Both properties: Safari still wants the prefix for mask-image on a gradient. */
	-webkit-mask-image: linear-gradient(
		to right,
		transparent,
		#000 var(--dfx-oem-fade),
		#000 calc(100% - var(--dfx-oem-fade)),
		transparent
	);
	mask-image: linear-gradient(
		to right,
		transparent,
		#000 var(--dfx-oem-fade),
		#000 calc(100% - var(--dfx-oem-fade)),
		transparent
	);
}

.dfx-oem-grid--carousel .dfx-oem-grid__list {
	flex-wrap: nowrap;
	justify-content: flex-start;
	width: max-content;
	/* The gap moves INSIDE the item below. Left here it would also fall between the two
	   halves of the track, making one join wider than every other and putting a visible
	   stutter in a loop that is otherwise seamless. */
	column-gap: 0;
	animation: dfx-oem-marquee
		calc(var(--dfx-oem-count, 6) * var(--dfx-oem-marquee-step))
		linear infinite;
}

/* Held while the pointer is over the row, and while anything inside it has keyboard
   focus — a mark that is a link cannot be activated if it is still moving. */
.dfx-oem-grid--carousel:hover .dfx-oem-grid__list,
.dfx-oem-grid--carousel:focus-within .dfx-oem-grid__list {
	animation-play-state: paused;
}

/* One column's share of what is in view, with the gutter as padding rather than a flex
   gap — see the join note above. The calculated basis from the static wall is replaced
   outright, not adjusted: it is a percentage of the track. */
.dfx-oem-grid--carousel .dfx-oem-grid__item {
	flex: 0 0 calc(100cqw / var(--dfx-oem-cols, 4));
	padding-inline: calc(var(--dfx-oem-gap) / 2);
	box-sizing: border-box;
}

@keyframes dfx-oem-marquee {

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

/* Stop the motion, and hand the row over to the scrollbar so the logos past the fold
   are still reachable. The duplicate halves stay in the markup — they are aria-hidden,
   and a second pass of the set at the end of a manual scroll is a smaller cost than
   serving different markup to a media query PHP cannot see. */
@media (prefers-reduced-motion: reduce) {

	.dfx-oem-grid--carousel .dfx-oem-grid__list {
		animation: none;
	}

	.dfx-oem-grid__viewport {
		overflow-x: auto;
	}
}

/* Cap rather than a fixed step, so the count never goes UP as the viewport narrows —
   which is what a per-value ladder produced when 7 and 8 were added. */
@media (max-width: 999px) {

	.dfx-oem-grid--cols-5 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-6 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-7 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-8 .dfx-oem-grid__list {
		--dfx-oem-cols: 4;
	}
}

@media (max-width: 690px) {

	/* 3.5rem between two columns on a phone is most of the viewport, so the gaps come
	   down here while the desktop values stay as set. Both are safe on the bare class
	   because nothing else sets either one below .dfx-oem-grid, so this wins by
	   inheritance — but only while that stays true. Any per-count gutter rule above
	   would score 0-2-0, beat this, and strand one column count at its desktop gap on
	   a phone. That is not hypothetical: it is what the reverted 7/8 tighten did. */
	.dfx-oem-grid__list {
		--dfx-oem-gap: 1.5rem;
		--dfx-oem-gap-row: 2.5rem;
	}

	/* THE COUNT IS ENUMERATED, and it has to be — the same fault the integrations
	   block documents, fixed here now the carousel depends on it. On the bare class
	   this scored 0-1-0 and lost to the .dfx-oem-grid--cols-N pair at 0-2-0, so a wall
	   set to 5 or more kept the 4 from the 999px block down to 320px and one set to 4
	   or fewer never stepped down at all — despite what the element description
	   promises. Specificity decides a custom property like any other declaration, and
	   sitting inside a later media query does not change a selector's weight.

	   Harmless-looking on a static wall, which is why it survived. Not harmless on a
	   scrolling row: four marks in view at 375px is about 80px each. */
	.dfx-oem-grid--cols-2 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-3 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-4 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-5 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-6 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-7 .dfx-oem-grid__list,
	.dfx-oem-grid--cols-8 .dfx-oem-grid__list {
		--dfx-oem-cols: 2;
		/* 5rem between two columns on a phone is most of the viewport. */
		--dfx-oem-gap: 1.5rem;
	}
}

/* ==============================================
   Integrations grid — the integrations logo wall
   ==============================================
   A mirror of the OEM grid block above, and deliberately so: the two walls can
   appear on one page and their marks have to share a center line. Same three height
   buckets, same calculated flex basis, same filter treatments. The VALUES are
   duplicated rather than shared, so a fifty-mark partner wall can be tuned without
   moving the seven-roundel manufacturer wall with it — but the RATIO CUT POINTS are
   not duplicated: they come off Oem_Meta's constants in PHP, because that is the
   part the shared center line actually depends on.

   The one-color treatments are filters over the single transparent asset:
   brightness(0) flattens every opaque pixel to black and preserves alpha, and
   invert(1) after it gives white. A mark exported onto an opaque box becomes a
   solid rectangle — the asset's fault, and what DSGN-692's compound-path rule
   exists to prevent. */

.dfx-integrations-grid {
	--dfx-integrations-box: 64px;
	--dfx-integrations-h-square: 40px;
	--dfx-integrations-h-mid: 52px;
	--dfx-integrations-h-wide: 64px;
	/* Column gap is a variable because the item width is calculated from it below.
	   3.5rem. The OEM wall was 5rem and has since been matched to this, so the two are
	   one value in two places — see the note there. The reason is set size rather than
	   taste: at five and six columns a wider gutter starves the cells and every mark
	   bottoms out against its height cap, which flattens the three buckets into one
	   and loses the thing they exist for. */
	--dfx-integrations-gap: 3.5rem;
	--dfx-integrations-gap-row: 3.5rem;
	/* Distance from a category heading to its own logos. A token because it is the
	   near half of a relationship — it has to stay visibly smaller than the gap
	   between groups, or a heading stops belonging to the wall beneath it. */
	--dfx-integrations-title-gap: 4rem;
}

.dfx-integrations-grid__title {
	margin: 0 0 2rem;
	font-size: var(--dfx-size-h2);
	line-height: var(--dfx-line-height-heading);
	letter-spacing: var(--dfx-letter-spacing-heading);
	text-align: center;
}

/* Grouped sections. The gap BETWEEN groups is larger than the row gap inside one,
   which is what makes a group read as a group rather than as a hole in the wall.
   Both are set here rather than on the group title's margin so the two distances
   stay in a visible relationship. */
.dfx-integrations-grid__group + .dfx-integrations-grid__group {
	margin-top: 4.5rem;
}

/* Category headings take the shared section-title treatment — the words, then a
   hairline filling the rest of the row — declared with .dfx-product-family__title
   and the rest further up this file rather than copied here. Same object as
   "Service Intelligence Platform" on /products/, so it should not be a second implementation that
   drifts. Type comes from `.dfx-h4` in the markup and the hairline from the
   shared rule; only the margin is local, 2rem, matching the family title for the
   reason recorded there.

   THE CLASS IS `__title--group`, NOT `__group-title`, AND THE NAME IS LOAD-BEARING.
   brand-base.css caps h1–h3 inside .container-wrap at 36ch and exempts component
   headings by convention with [class*="__title"]. That is a SUBSTRING match on two
   underscores immediately before `title`, so `__group-title` does not match it —
   the hyphen breaks it. This is an h3, so under the old name the cap applied and
   cropped the flex CONTAINER: the hairline stopped at 36ch with empty space beyond
   it, mid-section. Renaming brings it inside the convention instead of adding
   another `max-width: none` below, which is what that block exists to end. Do not
   tidy this back to a leading `group-`.

   2rem was too tight once the hairline landed: a ruled heading and the logos under
   it read as one block, so the label stopped separating from its own contents. The
   family title on /products/ does not have that problem because a card grid brings
   its own edges — a bare logo has none. Hence a local token rather than matching
   that 2rem. */
/* THE `.row .col` PREFIX IS LOAD-BEARING, NOT DEFENSIVE. Salient's style.css sets
   `.row .col h3, .row .col h4 { margin-bottom: var(--nectar-heading-bottom-spacing,
   8px) }` at 0-2-1, and this heading is an h3 inside a WPBakery column, so a
   single-class rule at 0-1-0 loses on specificity whatever value it carries — which
   is why the gap sat at 8px through 2rem, 3rem and 4rem alike. The doubled selector
   scores 0-3-0 and wins without !important, the same shape brand-base.css uses when
   it has to beat `.row .col h3`.

   THE SHARED SECTION-TITLE RULE ABOVE HAS THE SAME FAULT and is left alone here: its
   2.5rem is equally inert for .dfx-product-family__title and the four other titles in
   that list, all of which also render inside `.row .col`. That is five components and
   its own revert. */
.dfx-integrations-grid__title--group,
.row .col .dfx-integrations-grid__title--group {
	margin: 0 0 var(--dfx-integrations-title-gap);
}

/* Category description, under its heading. Measure is capped because this is body
   copy in a column as wide as the wall — 68ch is about where the eye starts losing
   the line. brand-base.css caps h1–h3 at 36ch inside .container-wrap but does nothing
   for a paragraph, so it is set here.

   THE FEATURE ARCHIVE'S GROUP SUMMARY IS LISTED HERE rather than declaring the same five
   properties beside its own block 2,000 lines up. A workflow group heading and a category
   group heading are the same object — linked term name, a line of term description, then
   the term's contents — and they are supposed to be indistinguishable, so sharing the
   declaration is what makes that true instead of aspirational. It had drifted on two of
   the five already: --dfx-line-height-ui at 1.45 against body's 1.6, and no measure cap
   at all, on an archive whose content column is the same 1100px as the wall's.

   THE GAP BELOW IS THE ONE THING NOT SHARED, and the split is deliberate rather than a
   loose end. Everything above the paragraph is identical on both surfaces because it is
   the same object either way — the type, the colour, the measure, and the 0.75rem bond to
   the heading. What sits BENEATH it is not the same object: a wall of partner logos on one,
   a text grid of feature names on the other. So the two rules below own their own distance
   to their own content, and the shared declaration owns everything that makes them look
   like one component. */
.dfx-integrations-grid__group-summary,
.dfx-feature-group__summary {
	margin: 0;
	max-width: 68ch;
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-body);
	color: var(--dfx-color-text-muted);
}

/* The wall keeps its token — 4rem, dropping to 2rem at ≤690px — which is the near half of
   the relationship its declaration describes. Unchanged. */
.dfx-integrations-grid__group-summary {
	margin-bottom: var(--dfx-integrations-title-gap);
}

/* 2.5rem ON THE ARCHIVE, WHICH IS THE ROW GAP, and the tie is the point rather than a
   collision. Everything inside a group is now one figure: description to first row, and
   row to row. The group reads as a single block against the 6rem that separates it from
   the next one, so the page has two distances instead of four and the hierarchy is legible
   from the spacing alone — 0.75rem binds the heading to its description, 2.5rem is
   "inside a group", 6rem is "a new group".

   IT IS NOT THE HIERARCHY FAULT THIS RULE USED TO CARRY, which is worth separating because
   the numbers look similar. That fault was 2rem below the description against a 2.5rem row
   gap: the intro copy sat CLOSER to row one than the rows sat to each other, so it read as
   part of row one. Equal is not closer. A tie makes the description a peer line inside the
   group; only a smaller value would have attached it to the first item.

   ONE VALUE AT EVERY WIDTH, so there is no ≤690px override. It had one, mirroring the
   integrations token's drop to 2rem, and that mirror existed only because the margin was
   read from that token — with its own figure there is nothing to mirror. Tightening on a
   phone would be the wrong instinct here for the reason the row gap records: every gap on
   a single-column stack sits between two full-width items, and they are taller because
   every description wraps further. */
.dfx-feature-group__summary {
	margin-bottom: 2.5rem;
}

/* With a description present the heading no longer needs the full gap — the paragraph
   is what separates the label from the logos now, and 4rem twice over would break one
   section into three pieces. Enough classes to clear the 0-3-0 above. */
.dfx-integrations-grid--summaries .dfx-integrations-grid__title--group,
.row .col .dfx-integrations-grid--summaries .dfx-integrations-grid__title--group {
	margin-bottom: 0.75rem;
}

/* Flex wrap rather than grid, so a short last row centers. CSS Grid cannot do that:
   with `1fr` tracks the columns fill the row whether or not items occupy them, so
   seven logos in four columns leave the trailing three hard against the left edge and
   justify-content has nothing to distribute. Widths still come out equal because the
   basis below is calculated, so this keeps the even columns and gains the centring. */
.dfx-integrations-grid__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	column-gap: var(--dfx-integrations-gap);
	row-gap: var(--dfx-integrations-gap-row);
	/* flex-start, not center: on the named layouts a two-line partner name makes its
	   item taller, and centring the ITEM would then drop that logo below the others.
	   Alignment of the marks themselves comes from the fixed-height box. */
	align-items: flex-start;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dfx-integrations-grid--cols-2 .dfx-integrations-grid__list { --dfx-integrations-cols: 2; }
.dfx-integrations-grid--cols-3 .dfx-integrations-grid__list { --dfx-integrations-cols: 3; }
.dfx-integrations-grid--cols-4 .dfx-integrations-grid__list { --dfx-integrations-cols: 4; }
.dfx-integrations-grid--cols-5 .dfx-integrations-grid__list { --dfx-integrations-cols: 5; }
.dfx-integrations-grid--cols-6 .dfx-integrations-grid__list { --dfx-integrations-cols: 6; }
.dfx-integrations-grid--cols-7 .dfx-integrations-grid__list { --dfx-integrations-cols: 7; }
.dfx-integrations-grid--cols-8 .dfx-integrations-grid__list { --dfx-integrations-cols: 8; }
.dfx-integrations-grid--cols-9 .dfx-integrations-grid__list { --dfx-integrations-cols: 9; }
.dfx-integrations-grid--cols-10 .dfx-integrations-grid__list { --dfx-integrations-cols: 10; }

/* NINE AND TEN GET A TIGHTER GUTTER, and they need it rather than prefer it. The
   3.5rem default is nine gaps at ten columns — around 500px of a 1300px container,
   leaving each cell under 80px, which bottoms every mark out against its height cap
   and flattens the three shape buckets into one. That is the same starvation the
   element's own help text warns about at 5–6 with the old 5rem gutter.

   2–8 ARE LEFT ALONE ON PURPOSE. Eight columns is already live on the workflow term
   archives at 3.5rem, and re-gapping it here would silently restyle those pages from
   a change whose subject is the product band. */
.dfx-integrations-grid--cols-9 .dfx-integrations-grid__list,
.dfx-integrations-grid--cols-10 .dfx-integrations-grid__list {
	--dfx-integrations-gap: 2rem;
}

/* The flex equivalent of a 1fr track: the row's width less its gaps, divided by the
   column count. The 0.02px comes off to absorb sub-pixel rounding — without it a full
   row can total a fraction over 100% and wrap its last item onto a line of its own. */
.dfx-integrations-grid__item {
	flex: 0 0 calc(
		(100% - (var(--dfx-integrations-cols, 5) - 1) * var(--dfx-integrations-gap))
		/ var(--dfx-integrations-cols, 5) - 0.02px
	);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.75rem;
	margin: 0;
	max-width: 100%;
}

/* Fixed height, so every logo box in a row is the same size and each mark centers
   inside its own. That is what puts a tall square badge and a wide horizontal lockup
   on one shared center line even though their caps differ. */
.dfx-integrations-grid__logo {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: var(--dfx-integrations-box);
}

/* Height is the constraint, not width — constraining width lets a tall square mark
   tower over a wide horizontal one. The default is the wide cap, which is also what
   an unbucketed logo gets. */
.dfx-integrations-grid__logo img {
	display: block;
	width: auto;
	max-width: 100%;
	height: auto;
	max-height: var(--dfx-integrations-h-wide);
	opacity: var(--dfx-integrations-alpha, 1);
}

.dfx-integrations-grid__logo--square img { max-height: var(--dfx-integrations-h-square); }
.dfx-integrations-grid__logo--mid img { max-height: var(--dfx-integrations-h-mid); }
.dfx-integrations-grid__logo--wide img { max-height: var(--dfx-integrations-h-wide); }

.dfx-integrations-grid--white .dfx-integrations-grid__logo img { filter: brightness(0) invert(1); }
.dfx-integrations-grid--black .dfx-integrations-grid__logo img { filter: brightness(0); }
.dfx-integrations-grid--grayscale .dfx-integrations-grid__logo img { filter: grayscale(1); }

/* THE NAME PLATE, for a partner with no Partner Logo on a logo wall. Four of the 64
   have none, and they used to be filtered out of the wall entirely — which under-reported
   the set on the hub and, worse, on a type archive claiming to list a whole category.

   NEUTRAL BECAUSE THE PALETTE IS ALREADY SPENT HERE. The featured badge below takes the
   component's single permitted Brass moment, so a second bordered pill in any accent
   would either fight it or dilute the rule. currentColor rather than the muted token for
   the same reason .dfx-integrations-grid__name inherits: the White treatment implies a
   dark band, where a fixed gray would be unreadable. Both text and border dim together.

   IT TAKES THE WALL'S OWN ALPHA, so a plate sits at exactly the presence of the grayscale
   marks beside it — 0.66 on the hub and the product band. A plate at full strength next
   to marks held at two-thirds reads as the emphasis of the row, which is the opposite of
   what a missing asset has earned.

   No uppercase and no letter-spacing, unlike the featured badge: that is a label, this is
   a company's name standing in for its wordmark, so it reads as the name it is. */
/* min-width: 0 IS THE LOAD-BEARING LINE HERE, and it was found by measuring rather than by
   reading. A grid item defaults to `min-width: auto`, so a nowrap plate sizes its own track:
   on the Service Intelligence Platform wall a "Stellantis wiADVISOR" plate took a 156px cell while every logo
   beside it sat at 109px, and `max-width: 100%` never bit because the track had already
   grown to fit. The row's rhythm broke rather than the plate being constrained. Capped here,
   the plate is bounded by its share of the wall like everything else.

   AND ONCE IT IS CAPPED, WRAPPING BEATS TRUNCATING. An earlier version used nowrap with an
   ellipsis, decided while the track was still growing — so the comparison was a wide plate
   against narrow ones rather than a tall plate against short ones. With the track fixed, a
   long name wraps inside its cell, stays completely readable, and the fixed 64px `__logo`
   box absorbs the extra line without moving the row. An ellipsis would have cost a partner's
   name to save a few pixels of height, which is the wrong way round for the one element on
   the page whose whole job is to name a partner that has no mark.

   Nothing in the current set wraps on a full-width six-column wall: the longest of the four
   names measures 156px against a 164px cell. That is only 8px of headroom, so a name much
   past "Stellantis wiADVISOR" will wrap — which is now the designed behavior rather than a
   defect, and the reason not to reach back for nowrap when it first happens. `title` stays on
   the plate regardless. A name long enough to need three lines sits slightly taller than its
   neighbours; no real partner does, and a rare tall plate is a better failure than a
   routinely unreadable one.

   `display: block` rather than inline-flex so the text is in a real block container; as a
   flex child of `__logo` it still shrink-wraps, so a short name is a short pill. */
.dfx-integrations-grid__item--wordmark {
	min-width: 0;
}

.dfx-integrations-grid__wordmark {
	display: block;
	max-width: 100%;
	padding: 0.375rem 0.75rem;
	border: 1px solid currentColor;
	border-radius: var(--dfx-radius-raised);
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	color: inherit;
	text-align: center;
	overflow-wrap: break-word;
	opacity: var(--dfx-integrations-alpha, 1);
}

/* A featured partner keeps full presence under every treatment, matching the img rule
   below it — the flag is the point of difference, so a plate must not be the one place a
   featured partner reads quieter than its neighbours. */
.dfx-integrations-grid .dfx-integrations-grid__item--featured .dfx-integrations-grid__wordmark {
	opacity: 1;
}

/* Hover parity with the marks. There are no colors to reveal on a plate, so presence is
   what resolves instead — the same gesture answered in the only currency a plate has. */
.dfx-integrations-grid--hover-color .dfx-integrations-grid__wordmark {
	transition: opacity 240ms ease;
}

.dfx-integrations-grid--hover-color .dfx-integrations-grid__item:hover .dfx-integrations-grid__wordmark,
.dfx-integrations-grid--hover-color .dfx-integrations-grid__item:focus-within .dfx-integrations-grid__wordmark {
	opacity: 1;
}

@media (prefers-reduced-motion: reduce) {

	.dfx-integrations-grid--hover-color .dfx-integrations-grid__wordmark {
		transition: none;
	}
}

/* A FEATURED PARTNER KEEPS ITS COLORS UNDER EVERY TREATMENT, in the featured section
   and in its own category alike — the flag is the point of difference, so it has to
   survive the thing that makes every other mark uniform. Full opacity too: a colored
   mark held at the wall's alpha would read as half-featured.

   Three classes to clear the treatment rules above at 0-2-1 outright rather than
   relying on source order, because these are the rules most likely to be reordered by
   someone tidying the block. */
.dfx-integrations-grid .dfx-integrations-grid__item--featured .dfx-integrations-grid__logo img {
	filter: none;
	opacity: 1;
}

/* Hover reveals the mark's own colors. The element only emits --hover-color when a
   treatment is actually applied, so there is no case where these rules animate
   nothing.

   THE TRIGGER IS THE ITEM, NOT THE IMAGE. A 12:1 wordmark is 16px tall; asking for
   the pointer to be on the mark itself would make the widest logos the hardest ones
   to reveal. The cell is a consistent target whatever the mark's proportions.

   `filter: none` rather than re-declaring the untreated value: it removes the
   treatment instead of guessing what it was, so one rule covers White, Black and
   Grayscale. Opacity goes to 1 in the same breath — a grayscale mark at 50% that
   colorises but stays half-visible reads as a rendering fault rather than a reveal.

   Both properties are transitioned on the image, and the transition is declared on
   the resting state so it eases out as well as in. */
.dfx-integrations-grid--hover-color .dfx-integrations-grid__logo img {
	transition: filter 240ms ease, opacity 240ms ease;
}

.dfx-integrations-grid--hover-color .dfx-integrations-grid__item:hover .dfx-integrations-grid__logo img,
.dfx-integrations-grid--hover-color .dfx-integrations-grid__item:focus-within .dfx-integrations-grid__logo img {
	filter: none;
	opacity: 1;
}

/* Reduced motion keeps the reveal and drops the easing — the information is the
   color, not the animation, so removing the transition costs nothing. */
@media (prefers-reduced-motion: reduce) {

	.dfx-integrations-grid--hover-color .dfx-integrations-grid__logo img {
		transition: none;
	}
}

/* Inherits the band's color rather than taking the muted token, because the White
   treatment implies a dark band and a fixed gray would be unreadable on one. Same
   reasoning, same values as .dfx-oem-grid__name — the two walls sit on the same
   bands and a partner name a step off a manufacturer name reads as a mistake. */
.dfx-integrations-grid__name {
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	color: inherit;
	opacity: 0.75;
	text-align: center;
}

/* --- Cards with descriptions: the hub layout ---------------------------------- */
/* NO SURFACE, DELIBERATELY, and this is the one place the element diverges from
   looking like the rest of the site's cards. .dfx-card--product is the only card
   surface in this file and it is a solid Obsidian fill; partner logos default to
   Original color, so enclosing them in it would force the whole hub onto the White
   treatment — and a one-color mark is permitted less often than it is convenient.
   An unenclosed row of logo, linked name and summary carries no such constraint.

   It follows that this layout borrows nothing from .dfx-card. An earlier draft put
   that class on the item; there is no bare `.dfx-card` rule in this file, so it was
   inert, and .dfx-card__body would have brought 2rem of padding with no surface
   under it.

   Left-aligned, unlike the two logo layouts: a centerd paragraph of two lines with a
   ragged second line reads as a caption, and this one is body copy. */
.dfx-integrations-grid--detail .dfx-integrations-grid__item {
	align-items: stretch;
	text-align: left;
	gap: 0.5rem;
}

/* The logo keeps its fixed box so marks still line up across a row, but sits left
   with the text rather than centerd over it. */
.dfx-integrations-grid--detail .dfx-integrations-grid__logo {
	justify-content: flex-start;
}

/* Full opacity and the h5 step here, overriding the wall's caption-sized, 0.75
   name: on this layout the name is the link into the integration, so it is the
   item's heading rather than a label under a mark. */
.dfx-integrations-grid--detail .dfx-integrations-grid__name {
	margin: 0;
	font-size: var(--dfx-size-h5);
	line-height: var(--dfx-line-height-heading-small);
	letter-spacing: var(--dfx-letter-spacing-heading-small);
	opacity: 1;
	text-align: left;
}

/* `inherit`, not a literal, for the reason .dfx-card__title a records: Salient's
   generated `body a { color: … }` sits at 0-0-2 and beats brand-base.css, so the
   anchor has to be named here. Inheriting means this needs no second edit if the
   band it sits on ever changes color. Brass on hover, matching the card. */
.dfx-integrations-grid--detail .dfx-integrations-grid__name a {
	color: inherit;
	text-decoration: none;
}

.dfx-integrations-grid--detail .dfx-integrations-grid__name a:hover,
.dfx-integrations-grid--detail .dfx-integrations-grid__name a:focus {
	color: var(--dfx-brass);
}

.dfx-integrations-grid__summary {
	margin: 0;
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-body);
	color: inherit;
	opacity: 0.85;
}

/* Shown by the script when the last category is unticked. An empty three-quarter
   column beside a live control reads as broken rather than as filtered. */
.dfx-integrations-grid__empty {
	margin: 0;
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-body);
	color: var(--dfx-color-text-muted);
}

/* The first group inside the filtered column must not carry the between-groups
   top margin, or the wall starts lower than the filter title beside it. */
.dfx-integrations-grid__main > .dfx-integrations-grid__group:first-child {
	margin-top: 0;
}

/* Shares the Integrations Grid's note treatment, because it is the same thing: an
   editor-only message about a gap on the page. Listed together so the two cannot drift
   into two different-looking warnings. */
.dfx-editor-note,
.dfx-integrations-grid__note {
	margin: 0;
	padding: 1rem 1.25rem;
	border: 1px dashed var(--dfx-brass);
	border-radius: var(--dfx-radius-raised);
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	font-style: italic;
	color: var(--dfx-color-text-muted);
}

/* ---------------------------------------------------------------------------
   Category filter: a quarter for the control, three quarters for the wall.
   ---------------------------------------------------------------------------
   NO LAYOUT DECLARED HERE, DELIBERATELY. The element emits Salient's own row and
   column classes — `.vc_row-fluid > .span_12` is already a flex container in
   grid-system.css, `.vc_col-sm-3`/`-9` are 25% and 75% above 691px and 100% below,
   and the 1% column padding against the row's -1% margins is the site's standard
   gutter. A private grid here would be a second implementation of all four, free to
   drift from every other column on the site.

   Sticky so the control stays reachable past the fold: the wall is fifty marks and
   the filter is the only way to shorten it. `start` rather than a pixel offset so it
   pins under whatever the header leaves. */
.dfx-integrations-grid__filter {
	position: sticky;
	top: 2rem;
	padding: 1.5rem;
	/* Signal White, the base surface token — not Signal #14C4B5, which the palette
	   reserves for in-flight motion and which would read as a status color on a
	   panel that has no status to report. On a white page this is the quietest way
	   to make the control a panel rather than loose text beside the wall. */
	background: var(--dfx-color-surface);
	/* Literal 10px, off the ramp on purpose: --dfx-radius-raised is 20px, which
	   reads as a card on a panel this tall and narrow. No token sits at 10. */
	border-radius: 10px;
}

/* Search field. Above the list because it is the coarser control — a name is a
   faster way to fifty marks than reading twelve category labels. */
.dfx-integrations-grid__search {
	margin: 0 0 1.25rem;
}

.dfx-integrations-grid__search-label {
	display: block;
	margin: 0 0 0.375rem;
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	color: var(--dfx-color-text-muted);
}

/* NOW ON THE SITE-WIDE FIELD SYSTEM, AND ALMOST EVERYTHING HERE IS GONE. This rule
   used to restate the whole frame — its own padding, fill, border, radius and focus
   ring — and every one of those had drifted from the values every other field on the
   site was using:

     radius   `var(--dfx-radius-input, 0.5rem)` — AND --dfx-radius-input HAS NEVER
              EXISTED. So this field has been rendering the 8px fallback while the
              contact form rendered 4px, and the fallback was accidentally right:
              SUI's field radius is 8. A token name with no definition is a value
              nobody can find, which is how a one-off survives an audit.
     height   none at all, so it sized from its own padding while every other field
              on the site took --dfx-field-height.
     fill     --dfx-color-surface-raised, reasoned about locally ("the one place
              white beats Signal White") — which is the exact reasoning the shared
              --dfx-field-fill token already carries, for the same reason.
     focus    a ring with no border-colour change, so this was the one field where
              focus did not move the frame.

   IT IS A FILTER, SO IT TAKES THE COMPACT HEIGHT — the same 40px the [dfx_forms]
   bar uses, from the same token, on the same reasoning: a control that sits beside
   content rather than being the content. The fill, border, radius, hover, focus,
   disabled and placeholder all now come from brand-base.css and are stated nowhere
   here. If this field ever needs to differ again, it needs a reason written down,
   not a local value.

   THREE CLASSES, WHICH IS THE ONE THING THIS RULE STILL HAS TO EARN. The shared
   height comes from `.container-wrap input[type="search"]` at 0-2-1, so a single
   class here would leave this field at the 48px form height — a class name is not
   automatically heavier than a type-plus-attribute selector, and that asymmetry is
   what the [dfx_forms] bar already solved the same way. 0-3-0 clears it. */
.dfx-integrations-grid .dfx-integrations-grid__filter .dfx-integrations-grid__search-input {
	width: 100%;
	height: var(--dfx-field-height-compact);
}

/* THE DOUBLED SELECTOR IS FOR THE BULLETS. Salient marks up lists inside
   .wpb_wrapper with their own list-style, which beats a lone `list-style: none` on
   a single class — this element now lives inside a real builder column, so it gets
   those rules like any other content. `li` is included because the marker can be
   set on either. */
.dfx-integrations-grid__filter-list,
.dfx-integrations-grid .dfx-integrations-grid__filter-list,
.dfx-integrations-grid .dfx-integrations-grid__filter-list > li {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* THREE CLASSES, AND THE SIBLING SELECTOR IS GONE. The old rule was
   `.item + .item { margin-top }` at 0-2-0, sitting behind the `> li { margin: 0 }`
   reset directly above it at 0-2-1 — so the gap it declared never rendered and the
   rows have always been flush. 0-3-0 clears the reset; a symmetric 6px on every
   item collapses to 6px between rows against the panel's own padding. */
.dfx-integrations-grid .dfx-integrations-grid__filter-list > .dfx-integrations-grid__filter-item {
	margin: 6px 0;
}

/* TYPE ONLY. THE CHECKBOX AND THE LAYOUT ARE BOTH GLOBAL NOW, and that is the whole
   of what changed here.

   This rule used to say "the checkbox is not styled at all", and it was right about
   what it wanted and wrong about what it got. The intent was that the control
   inherit the theme's own appearance rather than a second set defined locally — but
   the theme had no checkbox: its rule sat at 0-2-1 behind Salient's 0-2-3, so what
   these labels actually inherited was Salient's square 18.9px box with a
   `border-radius: 0` and a currentColor border. "Not styled" meant "styled by the
   parent theme", which is not the same thing and never was.

   The theme now draws a real SUI checkbox in brand-base.css and gives every
   checkbox and radio label the same flex row, so this component keeps only its
   type. The whole row is still the hit area — it is a <label> wrapping the input,
   so the text is clickable with no styling to make it so. */
.dfx-integrations-grid__filter-item label {
	cursor: pointer;
	font-size: var(--dfx-size-body-sm);
	line-height: var(--dfx-line-height-body);
}

/* THE `align-items: flex-start` OVERRIDE THAT USED TO SIT HERE IS GONE, AND IT IS
   WORTH SAYING WHY RATHER THAN JUST DELETING IT. It existed because Salient flexes
   checkbox labels with `align-items: center`, which floats the box halfway down a
   two-line category name instead of sitting it on the first line. That was a
   correct diagnosis of a global problem being fixed in one component: every
   wrapping checkbox label on the site had it, and only this one was fixed.

   `flex-start` is now the site-wide default for checkbox AND radio labels, in the
   label rule in brand-base.css — which also picks up the radio labels Salient never
   flexed at all. Keeping a local copy would be a second place to edit and a
   plausible place for the two to disagree. If this panel ever needs a different
   alignment, it needs a reason first. */

/* Featured badge. Cards layout only — the element does not render it on a logo wall,
   where the mark is the content and a label would compete with the thing it labels.
   Brass, and this is the one place in the component that earns it: the palette allows
   a single Brass moment per surface, so nothing else here may take it. */
.dfx-integrations-grid__badge {
	align-self: flex-start;
	padding: 0.125rem 0.5rem;
	border: 1px solid var(--dfx-brass);
	border-radius: var(--dfx-radius-raised);
	font-size: var(--dfx-size-caption);
	line-height: var(--dfx-line-height-ui);
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--dfx-brass);
}

/* ALIGNMENT MUST SIT AFTER THE --detail BLOCK ABOVE. Both classes are emitted on
   every instance and they carry the same specificity as the detail rules they
   override, so source order is the only thing making the outcome deterministic.
   Moved above the detail rules, a centerd Cards layout becomes unreachable.

   The element resolves an empty setting to left for Cards and center for a logo
   wall, so these are what the layouts already wanted — declared once here rather
   than repeated per layout. */
.dfx-integrations-grid--align-left .dfx-integrations-grid__list {
	justify-content: flex-start;
}

.dfx-integrations-grid--align-left .dfx-integrations-grid__item {
	align-items: flex-start;
}

.dfx-integrations-grid--align-left .dfx-integrations-grid__logo {
	justify-content: flex-start;
}

/* A LEFT-PACKED LOGO WALL STILL CENTERS ITS MARKS. Left there means the ROW packs from
   the left rather than distributing, which is what a narrow column needs; the cell
   edges do not move either way, so a mark held to the cell's left edge only widens the
   gap to its neighbour. The name-bearing layouts are excluded because their marks sit
   above left-aligned text, where flush left is the alignment. 0-3-0 beats the rule
   above outright, so this does not depend on staying below it. */
.dfx-integrations-grid--logos.dfx-integrations-grid--align-left .dfx-integrations-grid__logo {
	justify-content: center;
}

.dfx-integrations-grid--align-left .dfx-integrations-grid__title,
.dfx-integrations-grid--align-left .dfx-integrations-grid__name {
	text-align: left;
}

.dfx-integrations-grid--align-center .dfx-integrations-grid__list {
	justify-content: center;
}

.dfx-integrations-grid--align-center .dfx-integrations-grid__item {
	align-items: center;
}

.dfx-integrations-grid--align-center .dfx-integrations-grid__logo {
	justify-content: center;
}

.dfx-integrations-grid--align-center .dfx-integrations-grid__title,
.dfx-integrations-grid--align-center .dfx-integrations-grid__name {
	text-align: center;
}

/* A centerd Cards layout still wants its badge with the text rather than over it. */
.dfx-integrations-grid--align-center .dfx-integrations-grid__badge {
	align-self: center;
}

/* The category heading is a flex row carrying a hairline, so it stays hard left under
   either setting — text-align has nothing to act on in a flex container, and that is
   correct for both: the label wants the left edge with the rule running off it.
   Centring the label is a separate decision and would mean dropping the ::after. */

/* Three across at most on the detail layout whatever the element is set to: a row
   carrying a paragraph needs measure, and five across a 1440px band gives each about
   40 characters. Opens at 1000px so it meets the cap below at 999px with no gap. */
@media (min-width: 1000px) {

	.dfx-integrations-grid--detail .dfx-integrations-grid__list {
		--dfx-integrations-cols: 3;
		--dfx-integrations-gap: 2rem;
		--dfx-integrations-gap-row: 2.5rem;
	}
}

/* Cap rather than a fixed step, so the count never goes UP as the viewport narrows —
   the fault the OEM block records from adding 7 and 8. Enumerated rather than set on
   .dfx-integrations-grid__list alone because the cols-N rules above score 0-2-0 and a
   single-class selector would lose to them; the OEM block solves it the same way, and
   that is the reason neither needs !important. */
/* A MID STEP FOR NINE AND TEN ONLY, because 4 is too far to fall in one go. Ten
   columns needs roughly 1400px to give each mark a legible cell; below that the wall
   goes to six, and then to the four below.

   BEFORE the 999px block, not after, and that ordering is load-bearing. Both selectors
   score 0-2-0, a media query does not change the weight of the selector inside it, and
   so source order alone decides which wins where both match. Reversed, this rule would
   beat the 999px cap at every width below 1000px and a phone would render six. */
@media (max-width: 1399px) {

	.dfx-integrations-grid--cols-9 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-10 .dfx-integrations-grid__list {
		--dfx-integrations-cols: 6;
	}
}

/* The eight-to-six mid step that lived here was scoped to this page's cols-8 wall, and
   the wall is six across as authored again (2026-09-01), so nothing could match it. Six
   holds from 1000px up and the cap below takes it to four. */

@media (max-width: 999px) {

	.dfx-integrations-grid--cols-5 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-6 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-7 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-8 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-9 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-10 .dfx-integrations-grid__list {
		--dfx-integrations-cols: 4;
	}

	/* Two, not the four above: a tablet third of a row is about 30 characters, which
	   is a column of broken words rather than a summary. Last in the block so it
	   wins the 0-2-0 tie on source order. */
	.dfx-integrations-grid--detail .dfx-integrations-grid__list {
		--dfx-integrations-cols: 2;
		--dfx-integrations-gap: 2rem;
		--dfx-integrations-gap-row: 2.5rem;
	}
}

@media (max-width: 690px) {

	/* 3.5rem between two columns on a phone is most of the viewport, so the gap comes
	   down here while the desktop value stays as set. Row gap stays larger than the
	   column gap: stacked marks need the separation more than side-by-side ones.
	   Single class, so the gaps land on every variant. */
	.dfx-integrations-grid__list {
		--dfx-integrations-gap: 1.5rem;
		--dfx-integrations-gap-row: 2.5rem;
	}

	/* THE COUNT IS ENUMERATED, and it has to be. Setting it on
	   .dfx-integrations-grid__list alone scores 0-1-0 and loses to the
	   .dfx-integrations-grid--cols-N pair at 0-2-0 — specificity decides a custom
	   property exactly as it decides any other declaration, and a later media query
	   does not change the weight of the selector inside it. So a grid set to 5
	   would keep the 4 from the 999px block right down to 320px, silently, and
	   nothing about the rule looks wrong.

	   THE OEM BLOCK ABOVE HAD THIS FAULT and no longer does — it was enumerated when
	   the carousel landed, because four marks in view on a scrolling row at 375px made
	   a silent fault a visible one. */
	.dfx-integrations-grid--cols-2 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-3 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-4 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-5 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-6 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-7 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-8 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-9 .dfx-integrations-grid__list,
	.dfx-integrations-grid--cols-10 .dfx-integrations-grid__list {
		--dfx-integrations-cols: 2;
	}

	/* One across on the detail layout. Two 40%-width paragraphs on a phone is the
	   same measure problem as five across a desktop. Ties with the block above at
	   0-2-0 and wins on source order, which is why it sits after it. */
	.dfx-integrations-grid--detail .dfx-integrations-grid__list {
		--dfx-integrations-cols: 1;
	}

	.dfx-integrations-grid__group + .dfx-integrations-grid__group {
		margin-top: 3rem;
	}

	/* The heading gap has to come down with the group gap, not just because 4rem is
	   a lot of phone screen: at 4rem below against 3rem above, a heading sits closer
	   to the wall it introduces than to the one it follows, which reads as belonging
	   to the section above it. The near distance must stay the smaller of the two. */
	.dfx-integrations-grid {
		--dfx-integrations-title-gap: 2rem;
	}

	/* NO ARCHIVE MIRROR HERE ANY MORE. It existed only while the archive's summary read
	   the token above, and it now carries its own 2.5rem at every width — see the reason
	   stated on that rule. Removing it rather than leaving it at 2rem is the point: 2rem
	   under the description against a 2.5rem row gap is the inversion this file has now
	   corrected twice. */

	/* Stacking is Salient's — `[class*=vc_col-]` drops to 100% below 690px and gives
	   the column a 25px bottom margin. Only the sticky needs undoing: pinned above a
	   full-width wall it would sit over the logos rather than beside them. */
	.dfx-integrations-grid__filter {
		position: static;
	}
}

/* --- Term archives: workflow, integration type, family ---------------------- */
/* Written for /workflow/{slug}/ and now shared by the integration type and family
   archives, which assemble the same blocks and take the same rhythm. Named for all
   three so the next one to join is added here rather than given a section of its own.

   /workflow/{slug}/ — taxonomy-dfx_workflow.php.

   Almost everything here is a reuse rather than a new component: the band is
   .dfx-product-band, the section headings join the shared hairline rule, the
   features are .dfx-feature-index, and "How to get it" is the same
   .dfx-grid--products full of .dfx-card--product that the feature single now uses.
   What is left is the three things this page has that no other page does.

   THIS USED TO NAME A BUTTON JOINING .dfx-feature-single__cta-link, and that was true
   once: .dfx-workflow-page__cta-link shared those rules until DSGN-619 dropped this
   page's standalone Book a demo, at which point the selector came out of the lists and
   the line went stale. The rules themselves are now gone too — removed with the feature
   page's own closing CTA, on the stronger version of the same argument. Both pages have
   arrived at no CTA, from opposite directions. */

/* No inline custom properties are set on this band, unlike the product and feature
   singles — Band_Theme resolves color by walking a POST's product_category
   ancestors and a term has neither. That is why .dfx-product-band declares its
   fallbacks against --dfx-obsidian and --dfx-signal-white rather than assuming the
   vars exist: this variant relies on them entirely. */

/* THE BAND IS SHALLOWER THAN EITHER OF ITS SIBLINGS — 2rem top and bottom.

   Every rule touching the band lives HERE rather than beside the feature band's
   override up in the feature-page section, even though the reasoning is a
   continuation of it. One page's styles in one place: the alternative had half of
   this page's CSS at line ~3360 and half at the foot of the file, which is how a
   later change to one gets made without seeing the other.

   It was inheriting the product band's 7.5rem/5rem, which exists for the
   TRANSPARENT NAVIGATION on product singles. `dfx_product_transparent_nav_verdict()`
   is gated on `dfx_is_single_product()`, so this page gets a solid nav and a
   `#header-space` element already reserving its height — the padding was clearance
   for an overlap that does not happen. Same bug the feature band had, and the
   comment on that rule is the fuller account.

   SHALLOWER THAN THE FEATURE BAND'S 3.5rem because it carries less. A feature band
   holds an eyebrow, a title, a short description and a CTA button. This one holds a
   title and one line of summary: the eyebrow came out once the breadcrumb started
   rendering the same word, and there is no button. At 3.5rem it was mostly air.

   0,2,0, so it beats the base rule and its ≤999px variant at 0,1,0. One value at
   every width, for the reason the feature band takes one: 2rem is already as tight
   as a phone wants, so a second override would be a number to keep in step for no
   gain.

   SCOPED BY THE VARIANT CLASS, NOT BY THE ELEMENT. `.dfx-product-band__inner` is
   shared by every band, so setting padding on it directly would put product headlines
   under the transparent nav. Each variant class here exists on exactly one element in
   one template.

   THE INTEGRATION TYPE BAND JOINS IT rather than getting its own number, and carries
   even less — a title and nothing else, since that band has no eyebrow, no subhead and
   no button. If it ever wants a value of its own, split the selector then.

   THE FAMILY BAND JOINS IT TOO, and was the last term archive still inheriting the
   product band's 7.5rem/5rem — 426px of header against this group's 184px, on a page
   with a solid nav and a #header-space already reserving its height. It carries an
   eyebrow the other two don't, but no subhead and no button, so it sits nearer their
   load than the feature band's.

   AND THE FEATURE ARCHIVE BAND, which is new rather than converted — that template
   printed no band and no h1 at all. It carries exactly what the workflow band carries,
   a trail, a title and one line of subhead, so it takes that band's figure rather than
   arriving with a number of its own. Note the class is `--archive`: `.dfx-feature-band`
   is the feature SINGLE, which keeps its own 3.5rem because it also holds an eyebrow and
   a button. Two bands, two loads, two values, and the names now say which is which. */
.dfx-workflow-band .dfx-product-band__inner,
.dfx-integration-type-band .dfx-product-band__inner,
.dfx-family-band .dfx-product-band__inner,
.dfx-feature-archive-band .dfx-product-band__inner {
	padding-top: 2rem;
	padding-bottom: 2rem;
}

/* 2.5rem under the trail: more than the feature band's 2rem, well short of the
   product band's 5rem. Tried 1.25rem first and it crowded — the band's own padding
   came down to 2rem in the same pass, so the gap inside the band was tighter than the
   gap around it and the trail read as attached to the heading. */
.dfx-workflow-band .dfx-breadcrumbs,
.dfx-integration-type-band .dfx-breadcrumbs,
.dfx-family-band .dfx-breadcrumbs,
.dfx-feature-archive-band .dfx-breadcrumbs {
	margin-bottom: 2.5rem;
}
/* THE FAMILY PAGE JOINS BOTH OF THESE, and had neither: its sections butted at 0
   and its intro fell back to .dfx-lead's 66ch. The three archives assemble the same
   kinds of block from the same functions, so they take one rhythm rather than three. */
.dfx-workflow-page > * + *,
.dfx-integration-type-page > * + *,
.dfx-family-page > * + * {
	margin-top: 4rem;
}

/* The intro is the only unique prose on the page, so it gets the measure of body
   copy rather than the full container width. 62ch is the same limit the hero's
   constrained measure uses. */
.dfx-workflow-page__intro,
.dfx-integration-type-page__intro,
.dfx-family-page__intro {
	max-width: 62ch;
}

/* AND ITS LAST PARAGRAPH GIVES UP SALIENT'S TRAILING 30px, which was landing inside
   the 4rem above and reading as 94px. Salient sets `p { padding-bottom: 1.5em }`, so
   the intro box ends a line-and-a-half below its own last line of text and the section
   margin starts from there — on the integration type archive that put 108px of optical
   air between the intro and the logo wall against 88px on the other side of it, which
   is what Dave saw (2026-09-07). Zeroed only on the LAST child, so paragraph spacing
   inside a multi-paragraph intro is untouched. `> :last-child` is 0-2-0 against the
   bare `p` at 0-0-1, so no !important is needed. */
.dfx-workflow-page__intro > :last-child,
.dfx-integration-type-page__intro > :last-child,
.dfx-family-page__intro > :last-child {
	margin-bottom: 0;
	padding-bottom: 0;
}

/* OTHER INTEGRATION TYPES GETS A PANEL, AND ONLY THIS ONE OF THE FOUR TERM LISTS
   DOES. It is the last block on the page and the only one that is pure navigation, so
   a surface separates it from the content it is not part of. The family page's two
   lists are mid-page sections about the subject itself, where a box would assert a
   card; keeping them flat is the point of scoping to this class rather than sharing.

   NO BORDER AND NO RADIUS, BY REQUEST, WHICH MAKES THE CONTAINER INVISIBLE. Signal
   White measures about 1.005:1 against the page's own #F5F7F9, so with the edge gone
   the fill reads as nothing and only the padding survives. That is the intent: the
   white pills carry the section on their own and the box around them is dropped.

   BELOW `> * + *` BY NECESSITY: that rule is also 0-1-0, so the margin here only
   lands because this block comes after it. */
.dfx-integration-type-page__siblings {
	padding: 2.5rem;
	background: var(--dfx-color-surface);
	/* 3rem outside plus the 2.5rem padding inside. Was 2.5rem, on the reasoning that
	   40 + 40 reads as one gap — true of the boxes, but the logo cell is 64px tall
	   around marks that are 18–49px, so the wall's ink stops ~10px above its own
	   border and the gap a reader sees is smaller than the gap the numbers describe.
	   Measured on OEM Program: 88px of optical air below the wall against 108 above
	   it, when this block is the one that should be the more separated of the two.
	   With the intro's trailing 30px gone above, 3rem lands at 75 above and 96 below,
	   so the panel now reads as the new block it is. Half a step rather than a full
	   one because the invisible container (no border, Signal White on #F5F7F9) means
	   this margin is doing the separating on its own. */
	margin-top: 3rem;
}

/* 40px is most of a phone's measure once the container has taken its own padding, and
   the longest term name here is "Vehicle Data & Platforms". */
@media (max-width: 690px) {
	.dfx-integration-type-page__siblings {
		padding: 1.5rem;
	}
}

/* HANDLED BY needs no rules of its own. It renders through
   dfx_product_list_grid(), so it arrives wearing .dfx-grid--products and the card
   styles the /products/ hub uses — which is the point of going through that function
   rather than looping card.php here. The .dfx-workflow-products list this replaced is
   gone; if a rule for this section ever seems necessary, check first that it should
   not be on the card or the grid instead. */

/* BEFORE AND AFTER — the neighbouring workflows in service drive order.

   Two links, prev left and next right, and when only one exists it stays on its own
   side rather than centring: on the first and last terms in the sequence the
   position is the information. space-between with a single child would pull it left
   in both cases, so `next` is pushed over explicitly. */
.dfx-workflow-page__sequence {
	display: flex;
	flex-wrap: wrap;
	gap: 1.5rem;
	padding-top: 2.5rem;
	border-top: 1px solid var(--dfx-color-border-subtle);
}

.dfx-workflow-sequence {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	text-decoration: none;
	color: inherit;
}

.dfx-workflow-sequence--next {
	margin-left: auto;
	text-align: right;
}

.dfx-workflow-sequence__label {
	font-size: 0.8125rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--dfx-color-text-muted);
}

.dfx-workflow-sequence__name {
	font-family: var(--dfx-font-heading);
	font-weight: var(--dfx-weight-emphasis);
	color: var(--dfx-color-link);
}

.dfx-workflow-sequence:hover .dfx-workflow-sequence__name,
.dfx-workflow-sequence:focus .dfx-workflow-sequence__name {
	text-decoration: underline;
}

@media only screen and (max-width: 690px) {
	.dfx-workflow-page > * + * {
		margin-top: 3rem;
	}

	/* Stacked, so the left/right split that carried the prev/next distinction is
	   gone and the labels have to do it alone. Reset the alignment or the second
	   link reads as right-aligned for no reason. */
	.dfx-workflow-sequence--next {
		margin-left: 0;
		text-align: left;
	}
}

/* ============================================================================
   TIER COMPARISON TABLE — .dfx-tier-table
   ============================================================================

   THE FIRST STYLING THIS TABLE HAS EVER HAD. What shipped before was Salient's
   default table rendering — 12px, bold everything, a 1px border on all four
   sides of every cell — which is why 34 feature rows read as a spreadsheet.
   tier-comparison.php has said "those went with the rest of our table styling"
   since the min-width calculations were removed; this is the replacement.

   Structure borrowed from Linear's pricing table: no horizontal rules, vertical
   dividers between the tier columns only, group names as real headings, and
   space in place of weight. None of it depends on Linear's near-black surface,
   which is why the light theme is the default.

   ---------------------------------------------------------------------------
   WHY EVERY SELECTOR CARRIES `html body`, AND WHY IT IS NOT OPTIONAL
   ---------------------------------------------------------------------------
   Salient styles tables through four rules that all reach these cells:

     body:not(.woocommerce-cart) .main-content table              0-2-2
     body:not(.woocommerce-cart) .main-content td                 0-2-2
     body:not(.woocommerce-cart) .main-content th                 0-2-2
     body:not(.woocommerce-cart) .main-content tr th:first-child  0-2-3

   `:not(.woocommerce-cart)` contributes a class, so each is 0-2-2 or better
   against `.dfx-tier-table tbody td` at 0-1-2. Load order cannot save it —
   specificity is decided first — so a plain class rule loses border, padding,
   font-size and border-collapse wherever in the file it sits. Verified in the
   browser, not assumed: the first version of this block used plain class
   selectors and the table computed `border-collapse: collapse` with Salient's
   borders intact on every cell.

   `table.dfx-tier-table` rather than the bare class where the target IS the
   table, because 0-2-2 would only TIE Salient's rule and leave the outcome to
   enqueue order — which the page-submenu block above documents going wrong.

   Same escalation, same reason, as `html body .page-submenu li a`.

   ---------------------------------------------------------------------------
   ONE THEME BLOCK, TWO THEMES. Every rule reads a custom property and never a
   literal color, so `--inverse` repoints the same values and no rule is
   written twice. Add a color here and it must go in both blocks or they drift.
   ============================================================================ */

.dfx-tier-table-theme {
	/* THE EMPHASISED COLUMN, AS A TRANSLUCENT WASH RATHER THAN A COLOR, so it composites
	   over whatever band the table sits on instead of assuming one. Two opaque mixes were
	   tried and each was only right on one template. */
	--tt-tint:        color-mix(in srgb, var(--dfx-info) 8%, transparent);
	/* AN INK WASH FOR THE SAME REASON, so it darkens the tint and the bare band by the
	   same amount without knowing either. */
	--tt-hover:       rgba(0, 0, 0, 0.05);
	--tt-label:       var(--dfx-color-text-muted);
	--tt-value:       var(--dfx-color-text);
	--tt-group:       var(--dfx-color-text);
	--tt-divider:     var(--dfx-color-border-subtle);
	/* The fill behind a header cell, pinned or at rest. Opaque, unlike --tt-tint, because
	   rows scroll underneath it once pinned.

	   WHITE, NOT SIGNAL WHITE. This was --dfx-color-surface, which is the argument made
	   for the feature column below applied to only one cell: Signal White beside a tinted
	   or dark column reads as one more column treatment, and against the white cells
	   underneath it reads as a grey block. The whole header is white, and the emphasised
	   column overrides it at higher specificity. Dark mode is where this gets revisited. */
	--tt-head-bg:     var(--dfx-color-surface-raised);
	/* WHITE UNDER THE FEATURE COLUMN, NOT SIGNAL WHITE, and the two are not
	   interchangeable here. The tier columns carry a tint or a dark fill, so Signal White
	   beside them reads as one more column treatment; the feature column's own cells are
	   white, so the same value turns the corner cell into a grey block sitting on top of a
	   white column. `--dfx-color-surface-raised` rather than a literal #FFFFFF: it is the
	   token for a surface above the page, which is what a pinned cell is. */
	--tt-head-bg-feature: var(--dfx-color-surface-raised);
	/* INK, NOT A COLOR, and for the tint's reason: a #ECEEF0 hairline vanished where it
	   crossed the emphasised column, so the line broke into three segments per row.
	   Lighter than --tt-divider on purpose — one horizontal rule repeated 23 times
	   carries more weight than the two verticals do. */
	--tt-row-line:    rgba(0, 0, 0, 0.07);
	--tt-mark:        var(--dfx-baltic);
	/* 3.36:1 on Signal White. The first choice, #B9BEC6, measured 1.73 — under
	   the 3:1 WCAG 1.4.11 floor for a graphic that carries meaning. */
	--tt-absent:      #7E8794;
	--tt-accent:      var(--dfx-baltic);
	/* AN ADDED PRODUCT COLUMN. Signal White is the site's base surface, so a column
	   filled with it reads as the page showing through the table rather than as a
	   second emphasis competing with --tt-tint.

	   OPAQUE, UNLIKE --tt-tint, AND IT CAN BE: both surfaces this table sits on are
	   #FFFFFF — the features band opts out of Signal White (see
	   .dfx-product-section--features) and .container-wrap is white — so there is no band
	   for a wash to composite over. A Signal White band would make this column vanish;
	   that is the one thing to check before putting the table on a new surface. */
	--tt-product:     var(--dfx-signal-white);
}

.dfx-tier-table-theme--inverse {
	/* The same wash, heavier: it takes more of the mix to register on a dark ground. */
	--tt-tint:        color-mix(in srgb, var(--dfx-info) 16%, transparent);
	/* White, not black: an ink wash on a dark surface is invisible. */
	--tt-hover:       rgba(255, 255, 255, 0.06);
	--tt-label:       var(--dfx-powder);
	--tt-value:       var(--dfx-signal-white);
	--tt-group:       var(--dfx-signal-white);
	--tt-divider:     #26313F;
	--tt-head-bg:     var(--dfx-obsidian);
	/* No split on the dark surface: the feature column is Obsidian there too, so the
	   corner cell matching the rest of the header is already right. */
	--tt-head-bg-feature: var(--dfx-obsidian);
	/* White, same as --tt-hover: ink on Obsidian is invisible. */
	--tt-row-line:    rgba(255, 255, 255, 0.08);
	--tt-mark:        var(--dfx-arc);
	/* 3.69:1 on Obsidian. #4A5766 measured 2.27 — same failure as light. */
	--tt-absent:      #6B7787;
	--tt-accent:      var(--dfx-arc);
	/* NOT SIGNAL WHITE HERE. Literally reusing it would put a near-white slab through an
	   Obsidian table and make the added products the loudest thing on the band — the
	   opposite of the quiet grouping it does on light. A white wash is the same gesture
	   in this theme's own idiom: lift the column one step off the ground, as --tt-hover
	   and --tt-row-line already do. */
	--tt-product:     rgba(255, 255, 255, 0.05);
}

/* THE BAND GOES DARK WITH THE TABLE. Without this the Obsidian table sits on a
   Signal White band as a slab with a hard edge at the container width.

   `:has()` rather than a class on the section, because the section is printed by
   single-dfx_product.php while the surface is chosen by the element inside it —
   the parent cannot know. If :has() were unsupported the result is a dark table
   on a light band: ugly, not broken, so no fallback is needed. */
.dfx-product-section:has(.dfx-tier-table-theme--inverse) {
	background: var(--dfx-obsidian);
}

/* THE FOOTNOTE CENTERS ON THE TABLE'S AXIS, and `text-align` alone will not do it.
   The table is `margin: 0 auto` and narrower than the container, so both are centered
   on the same axis — but the footnote is a capped block pinned left, and centering the
   text inside a 66ch box only moves it within that box. It sat 259px left of the table
   on /packages. `margin-inline: auto` centers the box; text-align centers the line in
   it. Same pair, same reason, as `.container-wrap .col.center p` in brand-base.

   THE CAP IS RESTATED HERE RATHER THAN INHERITED, because it does not reach both
   templates: `.container-wrap p` caps the footnote at 66ch on a builder page, and the
   product bands are printed OUTSIDE `.container-wrap`, so on a product page the same
   paragraph ran the full 1100px and centering it did nothing visible. 66ch is the
   site's measure, not a new number.

   `text-align` ON THE ELEMENT, which is what lets it win inside the reveal:
   `.dfx-tier-comparison__reveal > .dfx-tier-comparison` sets `text-align: left` to stop
   `--center` reaching the table, and inherited alignment never beats a rule aimed at
   the element itself. The table cells keep stating their own alignment. */
/* The small print — the tick key and the numbered conditions — as one block below the
   table, separated from it by a rule.

   --tt-divider RATHER THAN THE RAW BORDER TOKEN, because this section sits inside the
   table's theme and the inverse surface has its own divider value. The raw token is
   #E3E5E7, which on Obsidian is a bright line rather than a subtle one.

   MICRO, THE TOKEN FOR FINE PRINT. The key inherited 16px body and the conditions were
   14px, which put a legend and a caveat at the weight of the copy above the table. Both
   are read once, after the answer.

   NO ALIGNMENT HERE. It stays on each child — see the tick key's own note for why an
   inherited value would lose inside the click-to-reveal wrapper. */
/* SHARED WITH THE FEATURE LIST'S SMALL PRINT, which is the same object under a different
   component: numbered conditions collected from the markers above them. Declared together
   rather than copied, because two rules would drift and the drift shows as the same
   footnote at two sizes on one product page — the table and the list are alternatives, so
   a reader moving between two product pages would see it. */
.dfx-tier-comparison__small-print,
.dfx-feature-list__small-print {
	max-width: 66ch;
	/* NO TOP MARGIN. The table's own 2rem bottom margin sets this gap and says so — both
	   would make it 4rem.

	   `margin-inline: 0`, NOT `auto`. The table is full width now, so the container's
	   left edge is the table's left edge, and starting there is what makes the key and
	   the conditions read as a note about the table rather than a centred block under
	   it. 66ch still caps the measure; it just runs from the left. */
	margin: 0 auto 0 0;
	font-size: var(--dfx-size-micro);
	line-height: var(--dfx-line-height-ui);
	color: var(--dfx-color-text-muted);
}

/* THE ONE VALUE THE FEATURE LIST CANNOT TAKE FROM THE RULE ABOVE: the gap over it. That
   rule zeroes the top margin because the TABLE's own 2rem bottom margin already sets the
   distance; the list has no such margin, so its last entry ends flush and the footnote
   rule landed 20px under it. 2rem restates the table's figure rather than inventing one,
   so the conditions sit the same distance below either surface.

   IT HAS TO SIT AFTER THE SHARED RULE, not up in the feature-list section where the rest
   of this component lives. Both are 0-1-0 and that one is a `margin` SHORTHAND, so
   declared earlier this would be overwritten by its own base. */
.dfx-feature-list__small-print {
	margin-top: 2rem;
}

/* `text-align` ON THE ELEMENT — the measure and the size moved up to the wrapper, this
   did not, and the reason is above.

   LEFT, MATCHING THE NUMBERED LIST BELOW IT. Centred, the key and the conditions
   disagreed about their own left edge, and the key's second line hung inside the first
   — a caption over a left-aligned table reads as part of the table only if it starts
   where the table does. */
.dfx-tier-comparison__footnote {
	margin: 0;
	text-align: left;
}

/* LEFT-ALIGNED INSIDE A CENTRED BLOCK, unlike the key. A centred list puts its numbers on
   a ragged left edge, which is the one thing a marker has to be scannable down.

   THE RULE BELONGS TO THIS LIST, NOT TO THE WRAPPER ABOVE IT, and putting it on the
   wrapper was wrong twice over. It drew above the tick key, which is a legend about the
   glyphs in the table rather than the start of the footnotes — and it drew whether or not
   any numbered condition existed, so a table with no conditions got a rule under it
   separating nothing from nothing. On the list, the border cannot outlive its content:
   the <ol> is only printed when there is a condition to print.

   Fallback on the divider because an undefined var with none makes the whole declaration
   invalid at computed-value time, and border-color then falls back to currentColor — a
   near-black rule where a subtle one was asked for. */
.dfx-tier-comparison__notes,
.dfx-feature-list__notes {
	margin: 1.25rem 0 0;
	/* NO LEFT PADDING, so the digits start on the same edge as the tick key above and
	   the table above that. The 1.5rem this had was room for `outside` markers, which
	   put the numbers in that gutter and the text at 1.5rem — a note about the table
	   beginning further in than anything it annotates. */
	padding: 1rem 0 0;
	border-top: 1px solid var(--tt-divider, var(--dfx-color-border-subtle));
	text-align: left;
	/* `inside` RATHER THAN padding: 0 WITH `outside`, which would have hung the digits
	   left of the content box and out past the table's edge. Inside puts the marker in
	   the first line's flow, so "1." starts flush; these conditions are a few words
	   each, so the second-line indent that comes with it has nothing to indent. */
	list-style-position: inside;
}

/* ON THE `li`, NOT ON THE `ol`, AND THAT IS WHY THE DIGITS VANISHED ONCE. The position
   was set on the list, which is inherited and ought to reach here — but Salient styles
   `li` directly with a `list-style` SHORTHAND, and a shorthand resets both halves of the
   property on the element it matches. So `inside` was discarded, the markers stayed
   `outside`, and dropping the list's left padding moved them out of the content box and
   off the left edge of the band, where nothing painted them.

   Same trap the feature list documents a few hundred lines up: inheriting anything about
   list markers into a Salient `li` does not work. Set it where the parent theme sets it.

   `decimal` restated for the same reason — the shorthand that clobbers the position
   clobbers the type beside it. */
.dfx-tier-comparison__notes li,
.dfx-feature-list__notes li {
	margin: 0;
	list-style: decimal inside;
}

/* THE MARKER IS A LINK AND MUST NOT LOOK LIKE THE FEATURE NAME BESIDE IT. Inherits colour
   rather than taking the link colour: at 0.7em beside a feature name, a blue digit reads
   as a typo. The underline is the affordance, and it waits for hover.

   THE FEATURE LIST'S MARKER IS THE SAME OBJECT, and `line-height: 0` is the declaration
   that makes sharing worth it there: without it a <sup> stretches its own line box, so one
   marked entry would sit taller than every other entry on the line. */
.dfx-tier-table__marker,
.dfx-feature__marker {
	margin-left: 0.15em;
	font-size: 0.7em;
	font-weight: var(--dfx-weight-emphasis);
	line-height: 0;
}

.dfx-tier-table__marker a,
.dfx-feature__marker a {
	color: inherit;
	text-decoration: none;
}

.dfx-tier-table__marker a:hover,
.dfx-tier-table__marker a:focus-visible,
.dfx-feature__marker a:hover,
.dfx-feature__marker a:focus-visible {
	text-decoration: underline;
}

/* The small print keeps --tt-label rather than --tt-value: it is muted against the body
   copy on the light surface, and inheriting the value colour would make it the brightest
   text under the table on the dark one. */
.dfx-tier-table-theme--inverse .dfx-tier-comparison__title {
	color: var(--tt-value);
}

.dfx-tier-table-theme--inverse .dfx-tier-comparison__small-print {
	color: var(--tt-label);
}

/* Horizontal scroll wherever the table cannot fit. No sticky header any more, so this
   carries none of the overflow caveats an earlier revision needed.

   UNCONDITIONAL, AND IT WAS GATED AT 999px. That held while a table was a feature column
   plus two or three tiers, which fits a desktop container. Added product columns break
   the assumption: 500px + four columns at 250px is 1500px, so a 1200px desktop viewport
   shrank the cells to min-content and then overflowed with no way to reach the far
   column. `overflow-x: auto` shows a bar only when there is something to scroll, so the
   narrow tables this used to cover are unaffected. */
.dfx-tier-comparison__scroll {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

/* THE STARTING OFFSET ONLY. The script overwrites this property per section with the
   measured bottom edge of whatever is pinned above the table — Salient moves the in-page
   menu at runtime, so the real figure is between 63px and 135px depending on where the
   header has slid to, and no static value is right in more than one state.

   4.5rem is the header's own height, which is the correct answer for a page that has no
   in-page menu and the safe answer before the first frame. */
.dfx-tier-comparison {
	--dfx-tt-sticky-top: 4.5rem;
}

/* --- Sticky header row -------------------------------------------------------------
   99 rows is what made this worth having: past the first screen there is no way to tell
   which column a tick belongs to.

   THE WRAPPER ABOVE IS WHY IT NEEDS A MEDIA QUERY AT ALL. `overflow-x: auto` forces the
   y axis to `auto` too, so that div — not the viewport — becomes the thead's scroll
   container, and `top` pins to a box with no vertical scroll. The sticky header does
   nothing at all rather than doing it badly, which is how it was lost the first time.

   So the overflow is lifted, and only where both conditions hold: a viewport wide enough
   that the table is not being squeezed, and a table narrow enough not to need the
   wrapper. The second is `--can-stick`, set in PHP off the column count.

   1200px IS THE TABLE'S NUMBER, NOT A DEVICE'S. Four tier columns measure 1100px inside
   the container; below roughly this the cells start hitting min-content and the wrapper
   has work to do again. Narrow viewports therefore keep horizontal scroll and no sticky
   header, which is not a compromise so much as arithmetic: a 1100px table cannot both
   scroll sideways and pin its header to the window. */
@media (min-width: 1200px) {

	.dfx-tier-comparison--can-stick .dfx-tier-comparison__scroll {
		overflow-x: visible;
	}

	/* ON THE CELLS, NOT ON <thead> OR <tr>. Sticky on a table-header-group or a row is
	   still unimplemented in Safari, so the cells are the only reliable target — which is
	   also why each one needs its own fill below. */
	.dfx-tier-comparison--can-stick .dfx-tier-table thead th {
		position: sticky;
		/* Clears Salient's fixed bar, measured at 72px. A variable so a header change is
		   one edit and not a hunt. */
		top: var(--dfx-tt-sticky-top, 4.5rem);
		z-index: 2;
	}

	/* PINNING CHANGES NOTHING ABOUT THE COLOUR, AND IT USED TO CHANGE THREE THINGS.
	   The fills lived here and only here, so the plain tier cells and the corner were
	   unpainted at rest and gained `--tt-head-bg` / `--tt-head-bg-feature` the moment
	   the header stuck. A column heading that recolours as the reader scrolls past it
	   reads as a different element arriving, not as the same one holding position.

	   Every header fill is now declared in the resting rules — the base `thead th`, the
	   emphasised column and the product column — so the stuck state inherits whatever
	   the cell already was. That also removes the reason the corner cell was special:
	   it takes the same fill as its row, at rest and pinned alike.

	   The shadow stays, because it is the one thing the pin genuinely adds: an edge
	   against the rows passing beneath. At rest the cell borders do that job. */
	.dfx-tier-comparison--can-stick.is-stuck .dfx-tier-table thead th {
		box-shadow: inset 0 -1px 0 var(--tt-divider);
	}

	/* THE POSITIONING SENTENCE GOES WHEN PINNED, and this is the whole reason the sentinel
	   and its observer exist. At rest the header is 240px of name, chip and a sentence per
	   tier; pinned, that is a quarter of a laptop screen held for the length of the table,
	   with four sentences repeating under the reader's eye the whole way down. Condensed it
	   is roughly 60px — name and chip, which is what a column heading is for.

	   `display: none`, NOT A max-height TRANSITION, AND THAT WAS A BUG. A collapsible
	   height needs a resting max-height to animate FROM, and any figure chosen for it is a
	   ceiling on real copy: 8rem clipped the Scheduling and Shop Management descriptions
	   mid-sentence, at rest, on every viewport wide enough to stick. The rest state now
	   declares nothing at all, so the paragraph is exactly what it was before this feature
	   existed, and the collapse is instant rather than clipped.

	   Instant also means nothing to exempt from prefers-reduced-motion. */
	.dfx-tier-comparison--can-stick.is-stuck .dfx-tier-table__tier-built-for {
		display: none;
	}
}

html body .dfx-tier-table-theme table.dfx-tier-table {
	/* FULL WIDTH, SO THE SMALL PRINT CAN SHARE ITS LEFT EDGE. This was `width: auto`,
	   which shrank the table to its columns and centred it — 1000px inside an 1100px
	   container on a two-tier product, with the leftover split either side. That made
	   the caption and the numbered conditions impossible to align with: they are
	   siblings of the scroll wrapper, so a centred table's left edge is a figure no
	   rule can name.

	   THE COST, STATED BECAUSE IT IS REAL. The column widths below are caps under
	   `table-layout: auto`, so a table that has to fill the container shares the slack
	   out pro rata and every cap is exceeded — 500/250/250 becomes roughly 550/275/275
	   on a two-tier product. The caps still hold their RATIO, which is what they were
	   protecting: the feature column stays twice a tier column, and no tier ends up
	   wide enough to strand a check mark. A five-tier product exceeds the container and
	   the wrapper scrolls, exactly as before.

	   Preferred over shrink-wrapping the whole component, which would have aligned the
	   section heading to the table too and put the `overflow-x: auto` scroll wrapper
	   inside a fit-content box — new behaviour at precisely the width where scrolling
	   starts. */
	width: 100%;
	/* 2rem BELOW, AND IT STILL HAS TO COME FROM HERE. The small print below has no top
	   margin of its own — deliberately, so this stays the one place the gap is set and
	   the two do not add up to 4rem. 1rem left it reading as one more row of the table
	   rather than a note about it.
	   Still well under the band's 5rem bottom padding, which is what keeps the small
	   print grouped with the table instead of floating between it and the next band. */
	margin: 0 auto 2rem;
	border: 0;
	/* SEPARATE, NOT COLLAPSE. Under `collapse` the borders belong to the table
	   rather than the cells, which puts a shared edge between the feature column
	   and the first tier column that neither cell can remove on its own. */
	border-collapse: separate;
	border-spacing: 0;
	/* 14px, up from Salient's 12px — the size was the single biggest legibility
	   problem. Linear's equivalent runs 16px, but the body ramp has no step
	   between --dfx-size-body-sm and --dfx-size-body, and inventing one here is
	   how a four-step scale becomes a five-step scale nobody agreed to. */
	font-size: var(--dfx-size-body-sm);
	line-height: 1.45;
	/* Explicit, not omitted: Salient's `.main-content table` paints the table box
	   white, so leaving this out does not mean "no fill" — it means Salient's. */
	background: transparent;
	color: var(--tt-value);
}

/* ---------------------------------------------------------------------------
   THE HEADER ROW

   NOT STICKY, and no fill of its own. An earlier revision pinned it under the
   in-page menu, which needed Salient's `body { overflow: hidden }` overridden
   to work at all — body was the scrollport, so the cell pinned to the document
   rather than the viewport. That override is gone with the stickiness; do not
   reintroduce one without the other.

   A HAIRLINE UNDER IT NOW, AND THIS BLOCK USED TO ARGUE THE OPPOSITE. The
   reasoning then was that the first group heading follows immediately and that
   heading is the break — true while every column was a tier of one product and
   the header row was four names of the same kind. Added product columns give the
   header row two kinds of thing side by side, so it stopped reading as a caption
   over the table and started reading as a first row of content. The rule is what
   makes it a header again.

   UNDER THE COLUMN HEADS ONLY, not across the full width. The feature column's
   header is empty by design — a visually-hidden "Feature" and nothing else — so
   a line under it would underscore blank space and make the rule look like it
   had lost a segment rather than like it started where the content does.
   --------------------------------------------------------------------------- */

/* SALIENT'S ZEBRA IS CLEARED OFF THE WHOLE TABLE, header and body alike. The row is
   where it has to happen — the cells are transparent, so nothing could be overridden
   cell-side. `body:not(.woocommerce-cart) .main-content table tr:nth-child(2n+1)` paints
   #FCFCFC, which put a slab behind the tier names and, in tbody, was the alternation the
   feature rows carried until the row lines replaced it.

   `:nth-child()` IS LOAD-BEARING IN BOTH SELECTORS, not a way of naming rows. Salient's
   rule measures 0-3-3 — `:not()` contributes `.woocommerce-cart` as a class and
   `:nth-child()` is class-level too — so `… .dfx-tier-table thead tr` at 0-2-4 lost.
   Two extra element names cannot answer a third class. The tbody selector matches the
   striped rows for the same arithmetic, not because the even rows need anything. */
html body .dfx-tier-table-theme .dfx-tier-table thead tr:first-child,
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:nth-child(2n+1) {
	background: transparent;
}

html body .dfx-tier-table-theme .dfx-tier-table thead th {
	/* TOP PADDING IS NOT OPTIONAL HERE, and it used to be 0. The emphasised column
	   paints a raised surface capped by a 2px accent, so a zero top put the tier
	   name against that cap with the fill showing nowhere above it. */
	padding: 1.25rem 1.5rem 1.125rem;
	border: 0;
	/* CLOSES THE HEADER ACROSS EVERY CELL, feature column included. This lived on
	   `:not(:first-child)` beside the border-left it shares a corner with, so the
	   hairline started at the first tier and the feature heading sat over open space —
	   visible as a notch wherever the table met the rows. Declared here instead so a
	   cell cannot be added without it; --tt-divider still matches the border-left. */
	border-bottom: 1px solid var(--tt-divider);
	/* THE HEADER'S OWN FILL, AT REST AND NOT ONLY WHEN PINNED. See the sticky block
	   above: painting it on `.is-stuck` alone meant the plain tier cells and the corner
	   changed colour the moment the header pinned. A column heading that recolours as
	   you scroll reads as a different element. The emphasised and product columns
	   override this at higher specificity, so they are unaffected. */
	background: var(--tt-head-bg);
	text-align: left;
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-emphasis);
	color: var(--tt-value);
	/* TOP, so the tier names line up with each other rather than with the hairline.
	   Bottom put them at different heights whenever one built-for line wrapped to a
	   different number of lines than its neighbour's. */
	vertical-align: top;
}

/* EVERY COLUMN IS CAPPED IN px, not shared out as a percentage — the feature column was
   38%, which left two tiers 392px each for a check mark in a column wider than the
   built-for line above it. 250px is what a tier header asks for, since
   `__tier-built-for` is capped at 24ch, and 500px is a comfortable measure for a
   feature name and its note.

   These are caps rather than fixed widths because the table sizes to its columns and
   the layout is AUTO: browsers honor a px width while the columns fit and shrink them
   proportionally when they do not, so a five-tier product degrades rather than
   overflowing. `table-layout: fixed` would collapse the widest column instead. */
html body .dfx-tier-table-theme .dfx-tier-table thead th:first-child {
	width: 500px;
}

/* THE CORNER CELL IS ALWAYS WHITE, and it keeps its own token rather than inheriting
   --tt-head-bg so that stays true if the header fill ever moves off white. Matched on
   the class and not on :first-child: the feature column is identified by
   `dfx-tier-table__feature` everywhere else in this file, and position is the weaker
   claim of the two. */
html body .dfx-tier-table-theme .dfx-tier-table thead th.dfx-tier-table__feature {
	background: var(--tt-head-bg-feature);
}

html body .dfx-tier-table-theme .dfx-tier-table thead th:not(:first-child) {
	width: 250px;
	/* The divider runs through the header row too — `border: 0` above took it off, so
	   the lines started at the first feature row and the header columns floated free.
	   The `:nth-child(2)` rule below still spares the first tier its left edge. */
	border-left: 1px solid var(--tt-divider);
}

/* FLEX, SO THE CHIPS SIT ON THE NAME'S CENTRE LINE. The name is 20px heading and the
   chips are 12px body, so baseline alignment hung them low and `vertical-align: middle`
   is measured off the parent's x-height rather than the line box. Wraps because the
   column is 300px and "Mastery Certification" plus a chip does not fit. */
.dfx-tier-table__tier-name {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--dfx-font-heading);
	/* --dfx-size-h4 (20px): the size the section titles take, and a tier name is
	   the same rank of thing. */
	font-size: var(--dfx-size-h4);
	font-weight: var(--dfx-weight-emphasis);
	letter-spacing: -0.01em;
	color: var(--tt-value);
}

.dfx-tier-table__tier-built-for {
	display: block;
	margin: 0.375rem 0 0;
	max-width: 24ch;
	font-size: var(--dfx-size-caption);
	font-weight: 400;
	line-height: 1.5;
	color: var(--tt-label);
}

/* BOTH CHIPS SIT INSIDE THE NAME NOW, so the flex gap spaces them and .dfx-badge's own
   0.5rem bottom margin would push them off the centre line. Zeroed for the pair rather
   than for the featured chip alone: the availability badge is beside it in the same span
   and has the same margin. */
.dfx-tier-table__tier-name > .dfx-badge {
	margin: 0;
}

/* ---------------------------------------------------------------------------
   THE EMPHASISED COLUMN

   AN OBSIDIAN HEAD OVER AN INFO-TINTED COLUMN, which is the tier card's
   arrangement: the head is the emphasis and the body of the column only has to
   stay quietly with it. The head therefore repoints --tt-value and --tt-label
   rather than setting `color` on each part — the name, the chip's neighbours and
   the built-for line all read those two properties already, so inheritance does
   the work and there is one place to change if the surface moves.

   NO ACCENT CAP ON THE HEAD ANY MORE. The 2px inset existed to mark a column
   whose only difference from its neighbours was a raised white; against Obsidian
   it is a hairline nobody sees, and the brand system does not spend a second mark
   where the first one landed.

   The tint breaks at each group heading, because that row is a single colspan
   cell and one cell cannot be two colors. It reads as the tint sitting behind
   the rows rather than as a broken column, which is why the colspan was worth
   keeping for the scope="colgroup" it restores.

   NOT COLOR ALONE: the column also carries the chip, so the emphasis survives
   grayscale.
   --------------------------------------------------------------------------- */
html body .dfx-tier-table-theme .dfx-tier-table thead th.dfx-tier-table__tier--featured {
	--tt-value: var(--dfx-signal-white);
	--tt-label: var(--dfx-powder);
	background: var(--dfx-obsidian);
	color: var(--tt-value);
}

/* ---------------------------------------------------------------------------
   AN ADDED PRODUCT COLUMN

   background-COLOR, NOT background-image, AND THAT IS THE WHOLE TRICK. The row
   hover paints `background-image`, and an image composites ABOVE a color — so
   the fill and the hover wash stack with no rule pairing them, which is what
   the emphasised column needs two rules to achieve. It also means a product
   column that is somehow also emphasised gets the tint over the fill rather
   than instead of it.

   HEADER AND BODY IN ONE SELECTOR LIST, unlike the emphasised column, because
   this fill is the same on both. The emphasised header is Obsidian and its
   cells are a light tint; there is nothing here to diverge.

   THE HEADER BOWS OUT WHEN THE COLUMN IS ALSO EMPHASISED, via `:not()` rather
   than by sitting earlier in the file. The emphasised header paints the
   `background` SHORTHAND, which resets background-color — so at equal
   specificity whichever rule came second would win, and this one is second.
   Only a hand-typed featured_tier can produce that column, but an ordering
   dependency that subtle is not worth leaving in for a case nobody can see.

   THE GROUP HEADING ROW'S CELL IS INCLUDED BY THE `td` SELECTOR — those cells
   carry the class too, from the template part. That is not incidental: the
   colspan revision of that row broke the emphasised column's tint at every
   group boundary, and an opaque fill would break more visibly.
   --------------------------------------------------------------------------- */
html body .dfx-tier-table-theme .dfx-tier-table thead th.dfx-tier-table__tier--product:not(.dfx-tier-table__tier--featured),
html body .dfx-tier-table-theme .dfx-tier-table tbody td.dfx-tier-table__cell--product {
	background-color: var(--tt-product);
}

/* A WASH OVER THE ROW, NOT A FILL, so the zebra shows through it and the alternation
   in this column is the row's own rather than a second one kept in step by hand.

   THAT SYNCHRONISING IS WHAT THIS REPLACES. Two opaque values — one mixed on the band,
   one on Salient's #FCFCFC stripe — held only where the ground was the colour the mix
   assumed. `.container-wrap` is #FFFFFF, so on a builder page the stripe is darker than
   its neighbours while on a product page's Signal White band it is lighter, and the
   column's light and dark rows came out inverted on /packages alone.

   background-IMAGE and not a translucent background-color, so the hover rule can stack
   a second layer over this one instead of replacing it. */
html body .dfx-tier-table-theme .dfx-tier-table tbody td.dfx-tier-table__cell--featured {
	background-image: linear-gradient(var(--tt-tint), var(--tt-tint));
}

/* ---------------------------------------------------------------------------
   GROUP HEADINGS

   ONE <tbody>, STYLED BY CSS, AND THE DIVIDERS RUN STRAIGHT THROUGH. Two earlier
   revisions each made the groups look like separate tables: the first opened a
   <tbody> per group, the second spanned the heading row with a single colspan
   cell. Both stopped the tier dividers — and the emphasised column's tint — at
   every group boundary, which is what "separate" was.

   Now the heading row carries an empty cell per tier, so the vertical lines and
   the tint are unbroken and the groups read as bands inside one table. There is
   deliberately no rule here touching the heading row's borders.

   The heading itself is a real h3–h5 inside the cell, sized by `.dfx-h4`. The
   tag/class split is the same one single-dfx_product.php uses for band titles:
   the tag is structure, the class is size. So no uppercase or tracking here —
   this is a heading now, not a label.
   --------------------------------------------------------------------------- */
html body .dfx-tier-table-theme .dfx-tier-table .dfx-tier-table__group th {
	padding: 2.75rem 1.5rem 0.5rem;
	border: 0;
	text-align: left;
}

/* The first group needs less air above it — the header row's hairline is right
   there. `:first-child` on the row, so it survives reordering. */
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:first-child.dfx-tier-table__group th {
	padding-top: 1.5rem;
}

.dfx-tier-table__group-title {
	margin: 0;
	color: var(--tt-group);
}

/* ---------------------------------------------------------------------------
   FEATURE ROWS

   ROW LINES, NOT A ZEBRA — see the block after the dividers. Vertical dividers
   separate the tier columns FROM EACH OTHER — never the feature column from the
   first tier, which is a label against data rather than two comparable things.

   `font-size: inherit` is required, not tidiness: Salient sets font-size on
   `.main-content td` directly, so the table's own size does not reach the cell
   by inheritance.
   --------------------------------------------------------------------------- */
html body .dfx-tier-table-theme .dfx-tier-table tbody th {
	padding: 0.625rem 1.5rem;
	border: 0;
	text-align: left;
	font-size: inherit;
	font-weight: 400;
	color: var(--tt-label);
}

html body .dfx-tier-table-theme .dfx-tier-table tbody td {
	padding: 0.625rem 1.5rem;
	border: 0;
	border-left: 1px solid var(--tt-divider);
	/* CENTRED, because the cell holds a mark and not a sentence. Left-aligned, a tick
	   in a 300px column hung off the divider with the rest of the column empty. */
	text-align: center;
	font-size: inherit;
	color: var(--tt-value);
}

/* The first tier column sits against the feature labels, not against another
   tier, so it takes no dividing line. `:first-of-type` and not `:first-child`:
   the row's first child is the feature `th`. */
html body .dfx-tier-table-theme .dfx-tier-table thead th:nth-child(2),
html body .dfx-tier-table-theme .dfx-tier-table tbody td:first-of-type {
	border-left: 0;
}

/* ---------------------------------------------------------------------------
   ROW LINES

   A HAIRLINE UNDER EACH FEATURE ROW, IN PLACE OF THE ZEBRA. The alternation was
   Salient's #FCFCFC stripe rather than anything chosen here, and it striped the
   group heading rows too — so the bands a reader was meant to see were cut across
   by a pattern on a different rhythm.

   NOT UNDER THE LAST ROW OF A SECTION, which is the whole point: the line groups
   the rows it sits between, and one under the last would close the section
   against its own whitespace and read as a rule above the next heading.

   ON THE CELLS, NOT THE ROW. `border-collapse: separate` above means a `tr`
   border does not paint — the cells own every edge in this table. */
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group) > th,
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group) > td {
	border-bottom: 1px solid var(--tt-row-line);
}

/* THE TWO WAYS A SECTION ENDS: the next group heading, or the end of the table.
   `:has(+ tr…)` is the only way to reach "last of its group" — the rows are all
   in one <tbody>, so there is no structural last child per section, by design
   (the group-headings block explains what a <tbody> per group cost).

   Unsupported :has() leaves a hairline above each heading. Ugly, not broken. */
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:has(+ tr.dfx-tier-table__group) > th,
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:has(+ tr.dfx-tier-table__group) > td,
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group):last-child > th,
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group):last-child > td {
	border-bottom: 0;
}

/* ---------------------------------------------------------------------------
   THE FEATURE COLUMN TAKES NO LEFT EDGE, and it needs its own rule at this
   specificity to say so.

   Salient's `body:not(.woocommerce-cart) .main-content tr th:first-child` puts a
   1px border there, and it measures 0-3-3 — `:not()` contributes its argument as
   a class AND `:first-child` is itself a class-level selector. That second class
   is the one easy to miss: the earlier `... tbody th` rule here was 0-2-4 and
   lost, which left a hairline down the left of every feature cell.

   Adding the element's own class takes these to 0-3-4, which wins outright rather
   than tying and depending on enqueue order. The group heading row carries the
   same class, so it is covered by the same rule.
   --------------------------------------------------------------------------- */
html body .dfx-tier-table-theme .dfx-tier-table thead th.dfx-tier-table__feature,
html body .dfx-tier-table-theme .dfx-tier-table tbody th.dfx-tier-table__feature {
	border-left: 0;
}

/* Orientation on a wide row, at the lightest wash that registers. Not on the
   group rows — they are headings, not data.

   A LAYER, NOT A FILL. The wash goes on background-IMAGE so each cell keeps its own
   background-color underneath: the accent mix this replaced was a `background`, so
   hovering the emphasised column blew the info tint away and the row lost its
   column. `--tt-hover` is ink rather than accent for the same reason — a translucent
   accent over a blue tint reads as a third color. */
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group):hover th,
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group):hover td {
	background-image: linear-gradient(var(--tt-hover), var(--tt-hover));
}

/* TWO LAYERS ON THE EMPHASISED CELL, hover over tint, because background-image is one
   property: the rule above would otherwise take the tint off the row being read. */
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group):hover td.dfx-tier-table__cell--featured {
	background-image:
		linear-gradient(var(--tt-hover), var(--tt-hover)),
		linear-gradient(var(--tt-tint), var(--tt-tint));
}

/* ---------------------------------------------------------------------------
   THE MARKS

   SHAPE AND FILL, NOT COLOR ALONE — a filled disc against a bare dash, so the
   distinction survives grayscale and color blindness. Both carry
   .screen-reader-text, because a tick with no text equivalent is an empty cell.
   --------------------------------------------------------------------------- */
/* A BARE CHECK, NOT A FILLED DISC. The disc was tried and rejected: at 34 rows a
   column of solid dots reads as heavier than the feature names beside it, and the
   brand system asks for restraint over decoration. The glyph alone still differs
   from the dash in shape, which is what the grayscale test needs. */
.dfx-tier-table__yes {
	color: var(--tt-mark);
}

.dfx-tier-table__no {
	display: inline-block;
	width: 1.125rem;
	text-align: center;
	color: var(--tt-absent);
}

/* ---------------------------------------------------------------------------
   ONE ROW HEIGHT, WHATEVER THE CELL HOLDS

   A row is as tall as its tallest line box, and the padding is constant, so the
   content decided the height: a tick made a 20.3px line box and a 41px row, an
   Add-on pill made 34px and a 55px row. Uniform rows read as a table; two
   heights read as a rendering fault, which is how this was reported.
   --------------------------------------------------------------------------- */

/* 8px OF THAT 14px WAS DEAD SPACE. `.dfx-badge` carries `margin: 0 0 0.5rem` for
   the card title, where it separates wrapped rows of chips; in a cell holding one
   chip it separates nothing, and inline-block margin counts toward the line box.
   The header already zeroes it on `.dfx-tier-table__tier-name > .dfx-badge`. */
html body .dfx-tier-table-theme .dfx-tier-table tbody .dfx-badge {
	margin: 0;
}

/* THE REMAINING 6px IS REAL — a pill is taller than a line of text — so the rows
   without one need a floor at the pill's height rather than the pill being shrunk
   to a line. 2.9375rem is that floor measured: a 26px chip (12px at 1.5 plus its
   0.25rem padding) inside the cell's 0.625rem padding. `height` on a table-row is
   a MINIMUM, so labels that genuinely wrap still grow past it.

   NOT A ::before STRUT ON THE `th`, WHICH IS WHAT THIS WAS AND WHY IT CHANGED. A
   zero-width inline-block does add the height and nothing else — but the cell's
   label is printed with a newline and fourteen tabs of indentation in front of it,
   and that whitespace is only discarded while it sits at the START of the line. Put
   any inline box before it and it becomes mid-line whitespace, collapses to one
   space, and indents the first line by 3.94px. Every wrapping label in the table
   read as hanging-indented backwards. The row height touches no inline box at all. */
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group) {
	height: 2.9375rem;
}

/* AND THE ROW FLOOR IS WHY THIS IS NEEDED. `vertical-align` is `baseline` by
   initial value on table cells — no rule sets it, and nothing here overrode it
   because until the floor existed a row was exactly as tall as its content, so
   baseline and middle rendered identically. The floor puts up to 6px of slack in
   every short row and baseline drops all of it below the content: the ticks sat
   4.6px high, the dashes 6.7px and the labels 7px.

   FEATURE ROWS ONLY. The group headings are excluded for the same reason they are
   excluded from the floor — they are headings, and their air is deliberate. */
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group) > th,
html body .dfx-tier-table-theme .dfx-tier-table tbody tr:not(.dfx-tier-table__group) > td {
	vertical-align: middle;
}

@media only screen and (max-width: 999px) {
	html body .dfx-tier-table-theme .dfx-tier-table thead th,
	html body .dfx-tier-table-theme .dfx-tier-table tbody th,
	html body .dfx-tier-table-theme .dfx-tier-table tbody td,
	html body .dfx-tier-table-theme .dfx-tier-table .dfx-tier-table__group th {
		padding-inline: 1rem;
	}
}

/* ============================================================================
   CASE STUDY SINGLE — single-dfx_case_study.php
   ============================================================================

   THE METRIC BAND IS THE REASON THIS COMPONENT EXISTS. The legacy stories kept
   their results inside stats_550*.jpg, so the numbers were invisible to search and,
   where the image host was malformed, invisible to readers too. Everything here is
   text, and nothing in this block should ever be given a background image.

   THE BAND SITS INSIDE .container, unlike the product page's derived sections. A
   product's bands are separate subjects; a case study's metrics are the lede of one
   argument, and a full-bleed rule between the dealer's name and their numbers cut
   the sentence in half. */

.dfx-case-metrics {
	margin: 0 0 2.5rem;
	padding: 2rem 0 0;
}

.dfx-case-metrics__title {
	margin: 0 0 1.25rem;
	color: var(--dfx-color-text-muted, #676E7E);
}

/* Flex rather than grid, so a trailing row centres instead of hanging left — the
   same reasoning the integrations wall records. --cols is set by the template from
   the row count, capped at four, because a lone 48% spread across four tracks reads
   as three missing numbers. */
.dfx-case-metrics__list {
	display: flex;
	flex-wrap: wrap;
	gap: 2rem 3rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dfx-case-metrics__item {
	flex: 1 1 calc((100% - (var(--dfx-case-metric-cols, 3) - 1) * 3rem) / var(--dfx-case-metric-cols, 3) - 0.02px);
	min-width: 8rem;
	margin: 0;
}

.dfx-case-metrics--cols-1 .dfx-case-metrics__list { --dfx-case-metric-cols: 1; }
.dfx-case-metrics--cols-2 .dfx-case-metrics__list { --dfx-case-metric-cols: 2; }
.dfx-case-metrics--cols-3 .dfx-case-metrics__list { --dfx-case-metric-cols: 3; }
.dfx-case-metrics--cols-4 .dfx-case-metrics__list { --dfx-case-metric-cols: 4; }

/* A single metric does not stretch to the full measure. On its own it would set a
   ~40px value against 1200px of whitespace, which reads as a layout fault rather
   than emphasis. South Dade Toyota is the live one-metric case. */
.dfx-case-metrics--cols-1 .dfx-case-metrics__item {
	flex: 0 1 22rem;
}

/* clamp() rather than a fixed size: "116%" and "12 min" and "30:1" all land here,
   and the longest of those at a fixed 3.5rem overflowed a four-column cell at
   1024px. Lower bound is the h2 step so it never drops below the body hierarchy. */
.dfx-case-metrics__value {
	margin: 0 0 0.35rem;
	font-size: clamp(2rem, 1.4rem + 2vw, 3.25rem);
	font-weight: 600;
	line-height: 1.05;
	letter-spacing: -0.01em;
	color: var(--dfx-baltic, #234F7C);
	font-variant-numeric: tabular-nums;
}

.dfx-case-metrics__label {
	margin: 0 0 0.4rem;
	font-size: 1rem;
	line-height: 1.4;
	color: var(--dfx-color-heading, #2B2F36);
}

/* THE QUALIFIER IS NOT DECORATION AND MUST NOT BE HIDDEN. These figures are four to
   seven years old; "Q2 2019 to Q2 2020" is what stops a 2020 result reading as a
   current claim about a named dealership (DSGN-627). Small, but at 0.875rem on
   Pewter it clears AA at 5.11:1 — it is fine print, not invisible print. */
.dfx-case-metrics__qualifier {
	margin: 0;
	font-size: 0.875rem;
	line-height: 1.45;
	color: var(--dfx-color-text-muted, #676E7E);
}

.dfx-case-dealer {
	margin: 0 0 2rem;
	padding: 0 0 1.5rem;
	border-bottom: 1px solid var(--dfx-color-border-subtle, #E3E5E7);
	font-size: 0.9375rem;
	color: var(--dfx-color-text-muted, #676E7E);
}

.dfx-case-body {
	margin: 0 0 2.5rem;
}

/* The pull quote is the page's voice, distinct from the several quotes in the body.
   Left rule rather than a card: a filled box here competed with the metric band
   directly above it, and the two were reading as sibling panels. */
.dfx-case-quote {
	margin: 0 0 1rem;
	padding: 0 0 0 1.5rem;
	border-left: 3px solid var(--dfx-baltic, #234F7C);
}

.dfx-case-quote__text {
	margin: 0 0 0.75rem;
	padding: 0;
	border: 0;
	font-size: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
	line-height: 1.5;
	font-style: normal;
	color: var(--dfx-color-heading, #2B2F36);
}

.dfx-case-quote__by {
	font-size: 0.9375rem;
	line-height: 1.5;
	color: var(--dfx-color-text-muted, #676E7E);
}

.dfx-case-quote__name {
	display: block;
	font-weight: 600;
	color: var(--dfx-color-heading, #2B2F36);
}

.dfx-case-quote__role,
.dfx-case-quote__dealer {
	display: block;
}

/* The full-bleed bands below .container-wrap. Alternating surface so "What they
   used" and "More proof" read as separate sections without a rule between them. */
.dfx-case-section {
	padding: 3.5rem 0;
}

.dfx-case-section--products {
	background: var(--dfx-color-surface, #F5F6F7);
}

.dfx-case-section--related {
	border-top: 1px solid var(--dfx-color-border-subtle, #E3E5E7);
}

/* THE DOUBLED SELECTOR IS NEEDED. An h2 inside a WPBakery column hits `.row .col h2`
   in brand-base.css at 0-2-1, which beats a single `.dfx-h4` at 0-1-0 — the same trap
   .dfx-related__band-title and .dfx-product-group__title both document. */
.dfx-case-section .dfx-case-section__title,
.row .col .dfx-case-section__title {
	margin: 0 0 1.5rem;
}

.dfx-case-related {
	display: flex;
	flex-wrap: wrap;
	gap: 1.25rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dfx-case-related__item {
	flex: 1 1 16rem;
	margin: 0;
}

.dfx-case-related__link {
	display: block;
	height: 100%;
	padding: 1.25rem;
	background: var(--dfx-color-surface, #F5F6F7);
	border: 1px solid var(--dfx-color-border-subtle, #E3E5E7);
	border-radius: var(--dfx-radius-raised, 1.25rem);
	text-decoration: none;
}

.dfx-case-related__link:hover,
.dfx-case-related__link:focus-visible {
	border-color: var(--dfx-baltic, #234F7C);
}

.dfx-case-related__value {
	display: block;
	font-size: 1.75rem;
	font-weight: 600;
	line-height: 1.1;
	color: var(--dfx-baltic, #234F7C);
	font-variant-numeric: tabular-nums;
}

.dfx-case-related__label {
	display: block;
	margin: 0.2rem 0 0.6rem;
	font-size: 0.9375rem;
	line-height: 1.35;
	color: var(--dfx-color-heading, #2B2F36);
}

.dfx-case-related__dealer {
	display: block;
	font-size: 0.875rem;
	color: var(--dfx-color-text-muted, #676E7E);
}

.dfx-case-cta__title {
	margin: 0 0 0.75rem;
}

.dfx-case-cta__body {
	margin: 0 0 1.5rem;
	color: var(--dfx-color-text-muted, #676E7E);
}

/* Salient's base button rule carries margin-bottom: 10px for builder rows, which is
   the trap .dfx-card__footer .nectar-button documents. Reset it here too. */
.dfx-case-cta__button.nectar-button {
	margin-bottom: 0;
}

/* Two across before one. Four metrics on a tablet at 4-up gave a 76px cell, the same
   starvation threshold the integrations wall records. */
@media (max-width: 999px) {

	.dfx-case-metrics--cols-3 .dfx-case-metrics__list,
	.dfx-case-metrics--cols-4 .dfx-case-metrics__list {
		--dfx-case-metric-cols: 2;
	}
}

@media (max-width: 690px) {

	.dfx-case-metrics--cols-2 .dfx-case-metrics__list,
	.dfx-case-metrics--cols-3 .dfx-case-metrics__list,
	.dfx-case-metrics--cols-4 .dfx-case-metrics__list {
		--dfx-case-metric-cols: 1;
	}

	.dfx-case-metrics__list {
		gap: 1.5rem;
	}

	.dfx-case-section {
		padding: 2.5rem 0;
	}
}

/* --- Tabbed section: restore Salient's own first-pane reveal ---------------- */

/* Salient 18.2.1 ships the tab JS and its CSS out of sync. `init.js` marks the
   open pane `.visible-tab`, but `element-tabbed-section.css` — the sheet that
   loads on tab pages — hides every pane unconditionally and never mentions that
   class; the rule honouring it lives in `element-food-item.css`, which is only
   enqueued for the Food Item element. So no pane shows until a click writes
   inline styles. These are Salient's own two rules, verbatim, so removing them
   after a theme update is safe once the reveal rule ships in a loaded sheet. */
.tabbed > .wpb_tab:not(.visible-tab) {
	display: none;
	visibility: hidden;
	position: absolute;
	opacity: 0;
	left: -9999px;
}

.tabbed > .wpb_tab.visible-tab {
	display: block;
	visibility: visible;
	position: relative;
	opacity: 1;
	left: auto;
}

/* Switching needs the third rule. Salient fades the incoming pane over 400ms,
   and that transition never advances here: it reports playState "running" with
   progress 0 and a startTime equal to the current timeline time, i.e. it restarts
   every recalculation, so the pane sits at its from-value of 0 forever. Inline
   `opacity: 1 !important` does not beat a running transition; removing the
   transition does. The cost is that panes swap instantly instead of fading. */
.tabbed > .wpb_tab {
	transition: none;
}

/* ============================================================================
   CLIENT FORMS  — [dfx_forms], the lists under /support/forms/
   ============================================================================

   A row is logo, label and note, then the outbound button. Not a card grid: these
   are documents to pick from, and a grid of 14 cards makes scanning for your own
   DMS harder than a list does. The live pages use a logo-per-block layout with the
   link as a heading, which is why they read as fourteen sections rather than one
   list of fourteen.

   NO NEW COLOR VALUES. Everything here resolves through existing tokens, and the
   only new visual idea is the row rule — a hairline between items, which is what
   separates a list from a stack of paragraphs without boxing each row. */
.dfx-forms {
	margin-block: 3rem;
}

/* 3rem ABOVE IS FOR A MID-PAGE SECTION, and on these pages the element is the first
   thing in the content — so that margin was 48px of nothing between the breadcrumb
   and the page's own h1. It stays for the case the value was written for: an
   element dropped below other builder rows, where it needs separating from them. */
.dfx-forms:first-child {
	margin-top: 0;
}

.dfx-forms__title {
	margin-bottom: 0.75rem;
}

/* The instruction line. Sits under the heading and above the first group, because
   it applies to the whole list — "select the link for your DMS" is not a property
   of any one row. Measure-constrained: it is a sentence, not a column. */
.dfx-forms__intro {
	max-width: 52ch;
	margin-bottom: 2.5rem;
	color: var(--dfx-color-body);
}

/* Group headings TAKE THE SHARED SECTION-TITLE PATTERN and declare almost nothing of
   their own — see the `.dfx-product-section__title` block above, which they now join.
   That pattern owns the flex row, the hairline fill, the gap and the 2.5rem below.

   This rule previously set its own margins and lost the hairline entirely, so the
   groups read as a different kind of heading from every other section on the site.
   Only `margin-top` and the anchor offset are local, because the shared rule
   deliberately sets `margin: 0 0 2.5rem` — it has no opinion about the space ABOVE a
   section, since on a product page each section sits in its own band.

   No `max-width` reset needed: brand-base.css already exempts
   `[class*="__title"]` from the 36ch cap, and with a flex fill that exemption is
   load-bearing rather than cosmetic — capped, the hairline would stop mid-section. */
.dfx-forms__title--group {
	margin-top: 3rem;
	/* Scroll-margin so an anchored group heading is not tucked under the header when
	   a rep sends /support/forms/#upgrade. The nav is solid on these pages, so this
	   is the header height plus a little air rather than the band's 7.5rem. */
	scroll-margin-top: 6rem;
}

/* The first group needs no space above it — the filter bar's own bottom border and
   margin already separate it, and 3rem on top of that reopens the gap this page has
   spent three commits closing. */
.dfx-forms__group:first-of-type .dfx-forms__title--group {
	margin-top: 0;
}

.dfx-forms__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* OPTING OUT OF THE PROSE MEASURE, which is what was making the rows half the width
   of the filter bar above them. brand-base.css caps reading width across the whole
   content area —

     .container-wrap p, .container-wrap li            max-width: 66ch
     .container-wrap h1, .container-wrap h2, h3       max-width: 36ch

   — and that is right for prose and wrong for a layout list. Each row measured
   666px against a 1345px column, and the group headings 419px, so the hairlines
   stopped two-thirds of the way across while the filter bar's border ran the full
   width. The rule is doing its job; these elements are simply not paragraphs.

   Three classes to clear `.container-wrap li` at 0-1-1. Worth knowing generally:
   ANY list-based component inside .container-wrap inherits that 66ch, so a wide
   table or card list will need the same opt-out.

   THE GROUP TITLE IS NOT LISTED HERE, though it was. brand-base.css already exempts
   `[class*="__title"]` on h1–h3 from the 36ch heading cap, so this was a second
   answer to a question already answered — and the wrong place for it, since with the
   shared section-title pattern's flex fill that exemption stops being cosmetic: a
   capped title crops the flex CONTAINER and the hairline stops mid-section. */
.dfx-forms .dfx-forms__list .dfx-forms__item {
	max-width: none;
}

/* THE ROW. Three tracks — logo, body, action — with the logo track collapsing to
   nothing when the form has no partner, which six of the 49 do not. `auto` rather
   than a fixed first column so those rows do not carry an empty gutter.

   `align-items: center` and not `start`: the action is a button and the body is one
   or two lines, so optical center is what lines them up. */
.dfx-forms__item {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: 1.25rem;
	padding-block: 1.25rem;
	border-bottom: 1px solid var(--dfx-color-border-subtle);
	/* Same reasoning as the group heading — a row can be the anchor target too, and
	   #form-form-dms-cdk-global is the finest grain a link can name. */
	scroll-margin-top: 6rem;
}

/* THE RULES SIT BETWEEN ROWS, NOT AROUND THE LIST. The first row's top border
   doubled with the group heading's own hairline directly above it, and the last row's
   bottom border closed the group off like a table — which reads as a box rather than
   as a list, and puts a line immediately above the next group's heading rule.

   Scoped per list rather than per section, because each group is its own `ul`: every
   group opens under its heading's hairline and ends without one. */
.dfx-forms__item:last-child {
	border-bottom: 0;
}

/* The logo plate. Fixed height, auto width, contained — the marks are 320x160
   uncropped at the `dfx_logo` size and vary wildly in aspect, so constraining the
   HEIGHT is what makes a row of them sit on one line. Width-limiting instead is the
   mistake the OEM grid worked through: every wide mark then dictates the track. */
.dfx-forms__logo {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 5.5rem;
}

.dfx-forms__logo-img {
	max-width: 100%;
	max-height: 2.25rem;
	width: auto;
	height: auto;
	object-fit: contain;
}

.dfx-forms__body {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	min-width: 0;
}

.dfx-forms__label {
	color: var(--dfx-color-heading);
	font-weight: var(--dfx-weight-emphasis);
}

/* The pre-filled flag, on the gray relationship chip rather than a status fill —
   it qualifies which VARIANT of a document this is, which is a relationship to its
   sibling row, not a state. Same reading the add-on chip gets on a product. */
.dfx-forms__flag {
	margin-left: 0.5rem;
	vertical-align: middle;
}

.dfx-forms__note {
	color: var(--dfx-color-text-muted);
	font-size: var(--dfx-size-body-sm);
}

/* The action. Deliberately a quiet outlined control rather than the primary CTA
   fill: there are up to eighteen of these on one page, and eighteen Brass buttons
   is the opposite of the brand's one-emphatic-moment-per-surface rule. The page's
   job is to let someone find their row, not to push them down it. */
/* `justify-self: end` AND `width: max-content` ARE BOTH LOAD-BEARING, and without
   them identical labels rendered at different widths — "Open in DocuSign" was
   290px on one row and 208px on the next.

   A grid item defaults to `justify-self: stretch`, so the anchor filled its whole
   track rather than sitting at its text width; and because each row is its own
   grid, the `auto` track resolved differently depending on how long that row's note
   was. The buttons were right-aligned and ragged on the left, with the label
   floating in the middle of a box sized by the sentence beside it.

   Pinning to content width makes the width a function of the label alone, which is
   what makes two "Open in DocuSign" buttons match. Rows whose provider differs
   still differ, and should. */
.dfx-forms__action {
	display: inline-flex;
	align-items: center;
	justify-self: end;
	width: max-content;
	box-sizing: border-box;
	height: var(--dfx-forms-field-height);
	padding: 0 1.125rem;
	border: 1px solid var(--dfx-color-border);
	border-radius: 999px;
	color: var(--dfx-color-link);
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-emphasis);
	text-decoration: none;
	white-space: nowrap;
}

.dfx-forms__action:hover,
.dfx-forms__action:focus {
	border-color: var(--dfx-color-link);
	color: var(--dfx-color-link-hover);
	text-decoration: none;
}

/* A form whose URL is unset. Renders as text, never as a button — see the note in
   the element. Muted and unbordered so it does not read as disabled-but-clickable. */
.dfx-forms__action--none {
	border-color: transparent;
	color: var(--dfx-color-text-muted);
	font-weight: 400;
}

/* Phones. The action drops under the body and the logo keeps its own column, so a
   row stays two lines rather than three — the button is the widest thing here and
   would otherwise squeeze the label to a couple of words per line. */
@media (max-width: 690px) {

	.dfx-forms__item {
		grid-template-columns: auto 1fr;
		gap: 0.875rem 1rem;
	}

	.dfx-forms__action,
	.dfx-forms__action--none {
		grid-column: 2;
		justify-self: start;
	}

	.dfx-forms__logo {
		width: 4rem;
	}
}

/* `[hidden]` LOSES TO EVERY `display` RULE IN THIS FILE, WHICH BROKE FILTERING
   ENTIRELY. The browser's own `[hidden] { display: none }` is a UA-stylesheet rule at
   zero specificity, so any author rule setting `display` outranks it — and the row is
   `display: grid`, the group `display: block`, the submit wrapper `display: flex`.

   The script set `row.hidden = true` correctly and nothing moved. The symptom was
   precise and misleading: the live count read "Showing 1 of 49 forms", because the
   count came from the same pass that set the attribute, so the logic was demonstrably
   right while the page showed all 49. The submit button gave it away twice over — it is
   hidden the same way, and it was still on screen.

   Declared for each element that sets `display`, rather than as a blanket
   `[hidden] { display: none !important }`: the blanket version is a real temptation
   here and it would silently override any future component that legitimately styles a
   hidden element. */
.dfx-forms__item[hidden],
.dfx-forms__group[hidden],
.dfx-forms__filter-submit[hidden],
.dfx-forms__filter-reset[hidden] {
	display: none;
}

/* ---- The filter bar --------------------------------------------------------

   A REAL GET FORM, RENDERED BY PHP AND STYLED UNCONDITIONALLY. It works with no
   JavaScript — the server reads the query string — so there is no state where these
   controls exist and do nothing, and nothing here waits for a class to become
   visible. That last part is deliberate: `display: none` plus a script-applied
   class is what broke the tabbed section when Salient deferred its init.js, and a
   page whose job is reaching a contract must not need script to be readable.

   The script hides its own submit button and toggles `.is-enhanced`. Both are
   subtractive — losing the script leaves a working form, not a broken one.

   A SIGNAL WHITE PANEL ON A WHITE PAGE. `.container-wrap` computes pure white here, so
   Signal White reads as a distinct surface rather than disappearing into it — and the
   fields inside go pure white in turn, so they sit ON the panel instead of dissolving
   into it. That inversion is why the fields no longer take Signal White as they did in
   the first pass: a field and its container cannot share a fill and still look like
   two things.

   The border stays. At 1.5:1 against white the panel edge is soft by design, and the
   hairline is what actually separates the bar from the first group heading. */
.dfx-forms__filter {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: 1rem;
	margin-bottom: 2rem;
	padding: 1.5em;
	background-color: var(--dfx-signal-white);
	/* NO BORDER. The Signal White fill is now what separates the bar from the list —
	   a filled panel with a rule along one edge only reads as an unfinished box. */
}

/* THE SUBMIT, AND THE ONE PLACE HERE THAT HAS TO FIGHT THE PARENT THEME.
   Measured, not guessed: Salient sets padding and border-radius on
   `button[type="submit"]` inside `.container-wrap` with `!important`, from three
   separate rules keyed on its own body data attributes —

     .container-wrap button[type="submit"]            border-radius: 0 !important
     body[data-button-style="rounded"] .container-wrap …  padding: 16px 23px !important
     body[data-form-submit="regular"] .container-wrap …   padding: 15px 22px !important

   plus a 200px radius and an Obsidian background from its accent-colour rules.
   The result was a 52px dark pill at 16px text beside 37px selects, which is what
   "the buttons are odd" was describing.

   Beating `!important` needs `!important` at equal-or-higher specificity, which is
   the same conclusion the footer h4 font-weight reached. The heaviest Salient
   selector here is 0-3-2, so this is 0-4-2 — `[type="submit"]` is in the selector
   to add weight, not to narrow it. */
body .dfx-forms .dfx-forms__filter button[type="submit"].dfx-forms__filter-button {
	height: var(--dfx-forms-field-height) !important;
	padding: 0 1.25rem !important;
	border: 1px solid var(--dfx-color-cta) !important;
	border-radius: 999px !important;
	background: var(--dfx-color-cta) !important;
	color: var(--dfx-color-cta-text) !important;
	font-family: inherit;
	font-size: var(--dfx-size-body-sm) !important;
	font-weight: var(--dfx-weight-emphasis);
	line-height: 1;
	cursor: pointer;
}

/* THE COLOUR SALIENT WAS ALREADY USING WAS RIGHT, and only the geometry was wrong —
   worth saying, because the first pass here replaced the background with Baltic
   before checking. Salient rendered it Obsidian, which is exactly
   `--dfx-color-cta`: the theme's own primary button pair is Obsidian filled with a
   Baltic hover, and SUI 2.0 specifies Obsidian pills. So this now names those
   tokens rather than a colour of its own, and the button matches every other
   primary button on the site instead of inventing a fourth blue. */
body .dfx-forms .dfx-forms__filter button[type="submit"].dfx-forms__filter-button:hover,
body .dfx-forms .dfx-forms__filter button[type="submit"].dfx-forms__filter-button:focus {
	background: var(--dfx-color-cta-hover) !important;
	border-color: var(--dfx-color-cta-hover) !important;
}

.dfx-forms__filter-field {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
}

/* The search field takes the slack so the selects stay at their content width —
   a vendor name is short, a search box wants room. */
.dfx-forms__filter-field--search {
	flex: 1 1 14rem;
}

/* A real <label>, not a placeholder. Placeholder-only labelling disappears the
   moment someone types, which is exactly when a screen reader user needs it, and
   it fails the theme's own accessibility floor. */
.dfx-forms__filter-label {
	color: var(--dfx-color-text-muted);
	font-size: var(--dfx-size-label);
	font-weight: var(--dfx-weight-emphasis);
	letter-spacing: 0.02em;
}

/* ONE HEIGHT FOR EVERY CONTROL IN THE BAR. Measured before the fix: the search
   input came out 48px, the selects 37px and the submit 52px — three heights in one
   row, which is what "field styling is inconsistent" was pointing at. Each came
   from a different source, so a single token is the only way they stay agreed. */
/* NOW AN ALIAS OF THE SITE-WIDE COMPACT TOKEN rather than its own number. This bar
   is a filter, so it takes --dfx-field-height-compact and not the 48px forms use —
   but the two now move together from brand-tokens.css instead of drifting. */
.dfx-forms {
	--dfx-forms-field-height: var(--dfx-field-height-compact); /* 40px */
}

/* THREE CLASSES, DELIBERATELY, AND THIS IS THE WHOLE FIX FOR THE MISSING BORDER.
   Salient styles text inputs from two rules that outweighed the single class this
   used to carry:

     input[type="search"]                      border: 2px solid transparent  (0-1-1)
     .container-wrap input[type="search"]      background-color: #fff         (0-2-1)

   So the border was not "going away" — it was being set to 2px of transparent, and
   the background to pure white rather than Signal White. At 0-3-0 this clears both
   without needing `!important`, which is why only the submit button below has any.

   `appearance: none` on the select as well, so the two fields agree on their frame
   instead of the select keeping the platform's. */
.dfx-forms .dfx-forms__filter .dfx-forms__filter-input,
.dfx-forms .dfx-forms__filter .dfx-forms__filter-select {
	box-sizing: border-box;
	height: var(--dfx-forms-field-height);
	margin: 0;
	padding: 0 var(--dfx-field-pad-x);
	border: 1px solid var(--dfx-field-border);
	border-radius: var(--dfx-field-radius);
	/* PURE WHITE, NOT SIGNAL WHITE, now the bar itself is Signal White — a field that
	   shares its container's fill stops reading as a field. This is also the value
	   Salient's own `.container-wrap input` rule was forcing, so the two now agree
	   rather than fighting; the specificity here is still needed for the border. */
	background-color: var(--dfx-field-fill);
	color: var(--dfx-field-text);
	font-family: inherit;
	font-size: var(--dfx-size-body-sm);
	line-height: 1;
}

/* THE DRAWN CHEVRON MOVED TO brand-base.css and is no longer restated here. It
   started as this component's fix for the platform chevron, then the contact form
   needed exactly the same thing — so it belongs to every select on the site, not
   to the filter bar. Keeping a second copy tuned to its own numbers is how the
   two drift. This rule now only carries what is specific to a compact bar. */
.dfx-forms .dfx-forms__filter .dfx-forms__filter-select {
	padding-right: calc( var(--dfx-field-icon-slot) + var(--dfx-field-pad-x) );
}

/* NOW THE SHARED FOCUS TREATMENT, AND THIS RULE WAS THE LAST CONTROL ON THE SITE
   STILL NAMING ITS OWN FOCUS COLOUR. It used --dfx-color-action (Arc) for both the
   border and the ring, at a 1px offset — so the filter bar focused in Arc while the
   contact form two clicks away focused in the shared token, and neither matched
   SUI's two-blue treatment.

   Every value here is now the same variable the fields and the selection controls
   read: blue-600 on the border, blue-500 on the ring, 2px wide with a 2px gap. The
   rule survives only because it has to restate the pair at 0-3-1 to clear Salient's
   input rules; it no longer decides anything.

   `:focus` RATHER THAN `:focus-visible` IS KEPT DELIBERATELY. The base rule in
   brand-base.css uses `:focus-visible`, which is right for a form field — a mouse
   click should not leave a ring behind. These are filter controls that re-run a
   query, and a visitor clicking through them benefits from seeing which one is
   active. Changing it would be a behaviour change, not a cleanup, so it stays and
   is now on the record as a choice. */
.dfx-forms .dfx-forms__filter .dfx-forms__filter-input:focus,
.dfx-forms .dfx-forms__filter .dfx-forms__filter-select:focus {
	border-color: var(--dfx-control-border-focus);
	outline: var(--dfx-control-focus-ring-width) solid var(--dfx-control-focus-ring);
	outline-offset: var(--dfx-control-focus-ring-gap);
}

/* Hover, which the bar did not have either — the shared rule in brand-base.css is
   0-2-1 and this component's own frame rule is 0-3-0, so the border colour set
   there won at rest AND on hover. Restated at matching weight so the bar picks up
   the site's hover step instead of sitting inert. */
.dfx-forms .dfx-forms__filter .dfx-forms__filter-input:hover:not(:focus),
.dfx-forms .dfx-forms__filter .dfx-forms__filter-select:hover:not(:focus) {
	border-color: var(--dfx-field-border-hover);
}

/* Text, not a button, and an anchor rather than `type="reset"` — a reset restores
   the form's initial values, which on a page loaded from a filtered URL are the
   filtered ones, so it would appear to do nothing. This is a link to the bare
   page, which is what clearing means. */
.dfx-forms__filter-reset {
	padding: 0.5rem 0;
	border: 0;
	background: none;
	color: var(--dfx-color-link);
	font-family: inherit;
	font-size: var(--dfx-size-body-sm);
	font-weight: var(--dfx-weight-emphasis);
	cursor: pointer;
	text-decoration: underline;
}

.dfx-forms__filter-reset:hover,
.dfx-forms__filter-reset:focus {
	color: var(--dfx-color-link-hover);
}

/* The live count. Its own full-width row so it does not fight the controls for
   space as the numbers change width. */
.dfx-forms__filter-count {
	flex: 1 0 100%;
	margin: 0;
	color: var(--dfx-color-text-muted);
	font-size: var(--dfx-size-body-sm);
}

/* Empty until the script writes to it, so it occupies nothing on a page that
   never filtered. */
.dfx-forms__empty:empty {
	display: none;
}

.dfx-forms__empty {
	margin-top: 1.5rem;
	color: var(--dfx-color-body);
}

@media (max-width: 690px) {

	.dfx-forms__filter {
		gap: 0.75rem;
	}

	/* Full width each: three stacked selects at content width look like a form
	   with a ragged right edge. */
	.dfx-forms__filter-field {
		flex: 1 0 100%;
	}
}

/* ---- Page breadcrumbs, above the title ------------------------------------

   Printed at `nectar_hook_after_outer_wrap_open`, which is the only place that
   lands ABOVE Salient's page header — see the note on dfx_page_breadcrumbs(). That
   puts it outside `.container-wrap`, so it brings its own `.container` for the
   gutter and needs its own vertical rhythm rather than inheriting the content
   area's.

   Padding rather than margin, because a margin here collapses against the page
   header's own top spacing on pages that have one, and the gap then differs
   depending on whether a header is enabled. */
.dfx-page-breadcrumbs {
	padding-top: 2.5rem;
	/* NO BOTTOM PADDING. `.dfx-breadcrumbs` already carries margin-bottom: 1.25rem,
	   which is the gap this needs and the same gap the trail has everywhere else.
	   Adding 8px here made it a fifth spacing in a stack that was already four deep. */
}

/* ZERO SALIENT'S CONTENT TOP PADDING WHEN THE TRAIL SITS DIRECTLY ABOVE IT.
   Salient core gives `.container-wrap` 40px top and bottom. That used to fall ABOVE
   the breadcrumb, because the trail rendered inside the wrapper; moving it out put
   the 40px BETWEEN the trail and the title instead, where it reads as a gap rather
   than as page inset.

   The adjacent sibling selector is doing real work: it matches only when nothing
   sits between the two — which is exactly the no-page-header case where the
   doubling happens. With a page header present they are not siblings, the 40px is
   below the header where it belongs, and this rule correctly does not fire.

   Same problem the `body:has()` fix addressed for full-bleed sections; here the
   relationship is direct enough not to need `:has()`.

   `body[data-header-resize]` IS IN THE SELECTOR FOR WEIGHT, NOT TO NARROW IT.
   Salient sets this padding twice — `.container-wrap` at 0-1-0 and
   `body[data-header-resize="0"] .container-wrap` at 0-2-2 — and the sibling
   selector alone (0-2-0) lost to the second one, which is why the 40px survived a
   first attempt at this. Matching any value of the attribute rather than "0" keeps
   it working whichever way the header-resize option is set. */
body[data-header-resize] .dfx-page-breadcrumbs + .container-wrap {
	padding-top: 0;
}

/* On a page whose header is a dark full-bleed band, the trail sits on the light
   surface above it — so the default light-page breadcrumb colours are correct and
   nothing needs restating. The band-scoped inversion further up this file is
   deliberately NOT reused: this element is never inside a band. */

@media (max-width: 999px) {

	.dfx-page-breadcrumbs {
		padding-top: 1.5rem;
	}
}

/* ==========================================================================
   TESTIMONIALS — [dfx_testimonials]
   The wall at /testimonials, and the quote bands on product pages. See
   inc/wpbakery-testimonials.php.
   ========================================================================== */

.dfx-testimonials {
	margin-block: 3rem;
}

/* Same reason as .dfx-forms:first-child — the 3rem is for a mid-page section, and on
   /testimonials the element is the first thing in the content. */
.dfx-testimonials:first-child {
	margin-top: 0;
}

.dfx-testimonials__intro {
	color: var(--dfx-color-text-muted);
	margin-bottom: 2rem;
}

/* MULTI-COLUMN, NOT GRID. Quotes run from 20 to 120 words, so grid rows would size
   every card to the longest one in the row and leave the short ones half empty.
   `columns` fills raggedly, which is what a quote wall wants — and it needs no
   JavaScript, which rules out anything Salient's delayed init.js could break. */
.dfx-testimonials__wall {
	columns: var(--dfx-testimonial-cols, 3);
	column-gap: 1.5rem;
}

/* THE MEDIA QUERIES BELOW SET `columns`, NEVER --dfx-testimonial-cols, AND THAT IS
   LOAD-BEARING. The element prints the variable as an INLINE style, which outranks
   every stylesheet rule no matter how specific — so re-declaring the variable here
   would silently lose and the wall would never step down. This is the same class of
   fault as the --dfx-oem-cols one, arrived at from the other direction: there the
   losing declaration was out-specified, here it would be out-ranked by an inline
   style that no selector weight can beat. Override the PROPERTY, not the variable. */
@media (max-width: 999px) {

	.dfx-testimonials__wall {
		columns: 2;
	}
}

@media (max-width: 782px) {

	.dfx-testimonials__wall {
		columns: 1;
	}
}

/* `break-inside: avoid` IS WHAT MAKES THE COLUMN LAYOUT USABLE. Without it a card
   splits across a column break and a quote continues in the next column under
   somebody else's name. */
.dfx-testimonials__card {
	break-inside: avoid;
	display: flow-root;
	margin: 0 0 1.5rem;
	padding: 1.5rem;
	background: var(--dfx-color-surface-raised);
	border: 1px solid var(--dfx-color-border-subtle);
	border-radius: var(--dfx-radius-raised);
}

.dfx-testimonials__media {
	margin-bottom: 1rem;
}

.dfx-testimonials__image {
	display: block;
	width: 100%;
	height: auto;
	border-radius: calc(var(--dfx-radius-raised) - 0.5rem);
}

.dfx-testimonials__quote {
	margin: 0;
	padding: 0;
	border: 0;
	font-style: normal;
}

/* SALIENT DRAWS ITS BLOCKQUOTE RULE AS A PSEUDO-ELEMENT, NOT A BORDER, which is why
   `border: 0` above looked like it should have removed it and did nothing.
   skin-material.css carries a bare `blockquote::before` — position absolute, height
   100%, width 4px, border-left 4px solid rgba(0,0,0,.1) — so the bar is a box the
   blockquote owns, and no border declaration on the blockquote itself can reach it.

   `content: none` removes the pseudo-element outright rather than trying to out-paint
   it. One class beats the bare element selector, so no !important is needed.

   NOT SOLVED BY DROPPING THE blockquote, which was the other option. The element is a
   quotation and the tag is correct; the cost of keeping it is this one rule. Note that
   style.css carries the same bar under `blockquote.wp-block-quote:before`, so a builder
   Quote block on the same page keeps its rule — this is scoped, not global. */
.dfx-testimonials .dfx-testimonials__quote::before {
	content: none;
}

/* OPTING THE QUOTE OUT OF THE PROSE MEASURE. brand-base.css caps
   `.container-wrap p` at 66ch across the whole content area, which inside a
   three-column wall is far narrower than the card and leaves a ragged right edge
   inside every card. The forms list documents the same escape hatch. */
.dfx-testimonials .dfx-testimonials__quote p {
	max-width: none;
	margin: 0 0 0.75rem;
	line-height: var(--dfx-line-height-body);
}

.dfx-testimonials .dfx-testimonials__quote p:last-child {
	margin-bottom: 0;
}

/* The quotation marks are added here rather than typed into the field, so an editor
   cannot produce a card with two sets of them. */
.dfx-testimonials__quote p:first-child::before {
	content: "\201C";
}

.dfx-testimonials__quote p:last-child::after {
	content: "\201D";
}

.dfx-testimonials__byline {
	margin-top: 1rem;
	font-size: 0.9375rem;
	line-height: 1.4;
}

.dfx-testimonials__name {
	display: block;
	font-weight: 600;
	color: var(--dfx-heading-ink);
}

.dfx-testimonials__detail {
	display: block;
	color: var(--dfx-color-text-muted);
}

.dfx-testimonials__video {
	display: inline-block;
	margin-top: 0.75rem;
	font-size: 0.9375rem;
	font-weight: 600;
}
