/**
 * Single Service — editorial layout.
 *
 * Sticky left rail (on-page TOC + specialist CTA) + right content column.
 * Type-led, quiet: no per-row dividers, no decorative ticks. Hierarchy is
 * carried by the kicker/title/group type tiers and whitespace.
 *
 * BEM blocks:
 *   .service-layout      two-column grid
 *   .service-rail        sticky aside (TOC + specialist CTA)
 *   .service-toc         on-page nav (desktop, in rail)
 *   .service-railnav     horizontal scroll-spy bar (tablet/mobile, under hero)
 *   .service-content     right content column
 *   .service-section     authored section (kicker + title + intro + groups)
 *   .service-group       titled capability group
 *   .service-caplist     tile-marker capability list
 *   .service-accred      inline accreditation trust strip
 *   .service-related     editorial related-services list
 */

@layer components {

	/* Anchor-jump offset for in-page TOC links. On mobile/tablet the sticky
	   horizontal scroll-spy bar sits below the header, so a jumped-to section
	   must clear BOTH (header + bar + breathing room). On desktop there's no
	   bar, so it only clears the header. One var, overridden per breakpoint;
	   used by every section's scroll-margin-top. */
	/* .editorial-single shares this rail system verbatim (blog / whitepaper /
	   case-study reuse the same .service-* layout, TOC, and scroll-spy). The
	   layout/component rules below are global bare-class selectors; only these
	   three custom props were scoped to the root, so both scope classes carry
	   them. One rail system, two entry classes — no duplicated CSS. */
	.service-single,
	.editorial-single {
		/* Real rendered header height, computed (not guessed): the header's
		   inner is min-block-size:var(--header-height) and .site-header adds
		   padding-block:var(--space-xs) top AND bottom. So the true height is
		   header-height + 2×space-xs. Using the exact composition self-corrects
		   if either token changes, and avoids the see-through sliver a rounded
		   guess (5rem) left between header and the sticky bar. */
		--svc-header-h: calc(var(--header-height) + var(--space-xs) * 2);
		--svc-anchor-offset: calc(var(--svc-header-h) + 3.5rem + var(--space-l));
		/* Rail wider than the global --sidebar-width (18rem) so industry
		   labels like "Drug Discovery & Development" sit on one line and the
		   TOC breathes. Scoped here — doesn't widen sidebars elsewhere. */
		--svc-rail-width: 20rem;
	}

	@media (min-width: 64em) {
		.service-single,
		.editorial-single {
			--svc-anchor-offset: calc(var(--svc-header-h) + var(--space-xl));
		}
	}

	/* LAYOUT — content-first column order; rail follows in source so the
	   horizontal scroll-spy bar (tablet/mobile) reads before the prose. */
	.service-layout {
		display: grid;
		grid-template-columns: 1fr;
		gap: var(--space-xl);
	}

	@media (min-width: 64em) {
		.service-layout {
			/* Content column fills the row to the right gutter (1fr) so it aligns
			   edge-to-edge inside .container, not floating centred. Reading
			   measure is owned by the prose itself (.service-section__intro
			   max-inline-size), so paragraphs stay readable while the column
			   reaches the gutter. */
			grid-template-columns: var(--svc-rail-width) 1fr;
			gap: calc(var(--container-gap) * 2.5);
			/* Leave the grid's default align (stretch) on the CONTAINER — the
			   content column must fill the row. The rail cell opts OUT of stretch
			   individually via `align-self:start` (below) so it can pin and
			   scroll within the tall row. Do NOT set align-items:start on the
			   container — that would collapse the content column too. */
		}

		/* Rail-less editorial content (no TOC, no cards) — a single centred
		   reading column instead of the two-column grid. */
		.service-layout--no-rail {
			grid-template-columns: minmax(0, var(--content-width-compact));
			justify-content: center;
		}
	}

	/* RAIL — desktop only. Below 64em the rail's contents (on-page TOC +
	   industries navigator) are replaced by the sticky horizontal scroll-spy
	   bar under the hero, so the whole rail is hidden: the industries
	   accordion has no place at the foot of a service page on mobile. */
	.service-rail {
		display: none;
	}

	/* Sticky lives on the GRID CELL itself (not a child wrapper) with
	   align-self:start. This is the bulletproof grid-sticky pattern: the cell's
	   containing block is the grid container (full content height), so the cell
	   has real travel room. Putting sticky on a child inside a stretched
	   `display:block` cell is the fragile variant that silently fails — the
	   child's containing block collapses and it flows normally despite
	   `position:sticky` computing. The earlier `overflow:clip`→`overflow-x:clip`
	   fix on #page (layout.css) is still required so no ancestor clips the
	   Y-axis. No height gate: the rail is shorter than any desktop viewport. */
	@media (min-width: 64em) {
		.service-rail {
			display: flex;
			flex-direction: column;
			gap: var(--space-xl);
			position: sticky;
			align-self: start;
			top: calc(var(--svc-header-h) + var(--space-l));
		}
	}

	.service-rail__sticky {
		display: flex;
		flex-direction: column;
		gap: var(--space-xl);
	}

	/* AUTHOR (rail variant) — compact, borderless; matches the quiet doc-rail
	   look of the TOC. Used by the blog single's editorial rail. */
	.vimta-author-rail {
		display: flex;
		flex-direction: column;
		gap: var(--space-s);
	}

	.vimta-author-rail__label {
		margin: 0;
		font-size: var(--text-2xs);
		font-weight: var(--weight-semibold);
		letter-spacing: var(--tracking-overline);
		text-transform: uppercase;
		color: var(--text-subtle);
	}

	.vimta-author-rail__person {
		display: flex;
		align-items: center;
		gap: var(--space-s);
	}

	.vimta-author-rail__avatar {
		flex-shrink: 0;
		inline-size: var(--avatar-l);
		block-size: var(--avatar-l);
		border-radius: var(--radius-round);
		overflow: clip;
		display: flex;
		align-items: center;
		justify-content: center;
		background-color: var(--avatar-bg);
		color: var(--avatar-text);
	}

	.vimta-author-rail__avatar-img {
		inline-size: 100%;
		block-size: 100%;
		object-fit: cover;
	}

	.vimta-author-rail__text {
		display: flex;
		flex-direction: column;
		gap: var(--space-3xs);
		min-inline-size: 0;
	}

	.vimta-author-rail__name {
		font-family: var(--font-heading);
		font-size: var(--text-m);
		font-weight: var(--weight-semibold);
		color: var(--text-main);
		line-height: var(--leading-tight);
	}

	.vimta-author-rail__role {
		font-size: var(--text-xs);
		color: var(--text-muted);
		line-height: var(--leading-snug);
	}

	.vimta-author-rail__bio {
		margin: 0;
		font-size: var(--text-s);
		line-height: var(--leading-body);
		color: var(--text-muted);
	}

	.vimta-author-rail__link {
		display: inline-flex;
		align-items: center;
		gap: var(--space-2xs);
		font-size: var(--text-s);
		font-weight: var(--weight-medium);
		color: var(--text-link);
		text-decoration: none;
	}

	.vimta-author-rail__link:hover {
		color: var(--text-link-hover);
	}

	/* ON-PAGE TOC (desktop, in rail) — hidden below the layout breakpoint;
	   the .service-railnav horizontal bar takes over there. */
	.service-toc {
		display: none;
	}

	@media (min-width: 64em) {
		.service-toc {
			display: block;
		}
	}

	/* TOC is a flex column: label → list spacing via gap, not margin. */
	.service-toc {
		display: flex;
		flex-direction: column;
		gap: var(--space-m);
	}

	.service-toc__label {
		margin: 0;
		font-size: var(--text-2xs);
		font-weight: var(--weight-semibold);
		letter-spacing: var(--tracking-overline);
		text-transform: uppercase;
		color: var(--text-subtle);
	}

	.service-toc__list {
		display: flex;
		flex-direction: column;
		gap: var(--space-2xs);
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.service-toc__item {
		margin: 0;
	}

	/* World-class doc-TOC treatment (Stripe / Linear / Tailwind docs):
	   no pill, no rail, no hover background. A 2px indicator line to the
	   left — transparent by default, primary on active. Inactive text is
	   muted; hover just darkens it; active is primary + semibold. The
	   colour and the line are the only signals. */
	.service-toc__link {
		display: block;
		padding-block: var(--space-3xs);
		padding-inline-start: var(--space-m);
		font-size: var(--text-s);
		font-weight: var(--weight-medium);
		line-height: var(--leading-snug);
		color: var(--text-muted);
		text-decoration: none;
		border-inline-start: var(--stroke-strong) solid transparent;
		transition: color var(--duration-fast) var(--ease-default),
			border-color var(--duration-fast) var(--ease-default);
	}

	.service-toc__link:hover {
		color: var(--text-main);
	}

	.service-toc__link.is-active {
		color: var(--primary);
		font-weight: var(--weight-semibold);
		border-inline-start-color: var(--primary);
	}

	.service-toc__link:focus-visible {
		outline: var(--focus-ring);
		outline-offset: var(--focus-ring-offset);
		border-radius: var(--radius-xs);
	}

	/* HORIZONTAL SCROLL-SPY BAR (tablet/mobile, under hero).
	   Modern underline-indicator nav — quiet labels, active = near-black
	   text with a sliding 2px underline riding a faint hairline. */
	.service-railnav {
		display: block;
		position: sticky;
		/* Stick below the REAL header height, not the token min, so the bar
		   pins flush under the header instead of overlapping it / letting
		   content peek through the height mismatch. */
		top: var(--svc-header-h);
		z-index: var(--z-sticky);
		background: var(--surface-raised);
		border-block-end: var(--divider);
		/* Gutter on the bar itself — .container only constrains max-width, it
		   carries no inline padding (that normally comes from .section, which
		   this full-bleed sticky bar is not). Without this the tabs touch the
		   viewport edge below --content-width. Matches the site gutter. */
		padding-inline: var(--gutter);
		/* Soft shadow so content reads as passing UNDER the pinned bar
		   instead of butting flush against its edge — the depth cue that was
		   missing when scrolling manually. */
		box-shadow: var(--shadow-s);
	}

	@media (min-width: 64em) {
		.service-railnav {
			display: none;
		}
	}

	/* Content section sits directly under the sticky tab bar — the bar + its
	   shadow already separate it, so the section's full --section-space-l top
	   pad reads as a dead gap. Trim the TOP only; bottom keeps its rhythm.
	   Tighter on mobile (where the gap read worst), roomier on desktop. */
	.service-railnav + .section {
		padding-block-start: var(--section-space-s);
	}

	@media (min-width: 64em) {
		.service-railnav + .section {
			padding-block-start: var(--section-space-m);
		}
	}

	/* The opening heading of the first content section must not inherit the
	   --space-xl top margin that .entry-content headings carry mid-flow —
	   there's nothing above it but the section's own top padding, so the
	   margin reads as a dead gap under the tab bar. Zero it on the first
	   section's intro only; mid-content headings keep their separation. */
	.service-content > .service-section:first-child .service-section__intro > :is(h1, h2, h3, h4, h5, h6):first-child {
		margin-block-start: 0;
	}

	.service-railnav__list {
		display: flex;
		gap: var(--space-2xs);
		margin: 0;
		padding: 0;
		list-style: none;
		overflow-x: auto;
		scrollbar-width: none;
		scroll-snap-type: x proximity;
	}

	.service-railnav__list::-webkit-scrollbar {
		display: none;
	}

	.service-railnav__item {
		margin: 0;
		flex: 0 0 auto;
		scroll-snap-align: start;
	}

	.service-railnav__link {
		display: inline-flex;
		align-items: center;
		padding-block: var(--space-s);
		padding-inline: var(--space-2xs);
		font-size: var(--text-s);
		font-weight: var(--weight-medium);
		color: var(--text-subtle);
		text-decoration: none;
		white-space: nowrap;
		border-block-end: var(--stroke-strong) solid transparent;
		transition: color var(--duration-fast) var(--ease-default),
			border-color var(--duration-fast) var(--ease-default);
	}

	.service-railnav__link:hover {
		color: var(--text-main);
	}

	.service-railnav__link.is-active {
		color: var(--text-main);
		font-weight: var(--weight-semibold);
		border-block-end-color: var(--text-main);
	}

	.service-railnav__link:focus-visible {
		outline: var(--focus-ring);
		outline-offset: calc(var(--focus-ring-offset) * -1);
	}

	/* RAIL INDUSTRIES NAVIGATOR — the shared industry-sidebar component
	   renders here (styles come from page-industry.css, already enqueued
	   for service singles). Only the inner-wrapper margin is reset so it
	   sits flush in the sticky rail flex column. */
	.service-rail .industry-sidebar__inner {
		display: flex;
		flex-direction: column;
		gap: var(--space-l);
	}

	/* The accordion labels are sized for the full-width industry-page sidebar
	   (--text-m); in the narrower 20rem V2 rail the long parent names wrap to
	   two lines. Scope a smaller label + tighter padding to THIS rail only —
	   the component stays unchanged where it renders at full width. */
	.service-rail .industry-accordion__link {
		font-size: var(--text-s);
		padding-inline: var(--space-s);
	}

	.service-rail .industry-accordion__child-link {
		font-size: var(--text-s);
	}

	/* CONTENT COLUMN */
	.service-content {
		/* Reading text uses the global --text-m (standardised to 17→19px),
		   so the V2 column stays in lock-step with the rest of the theme —
		   no bespoke override. */
		display: flex;
		flex-direction: column;
		/* Inter-section gap must out-separate the within-section head→body gap
		   (--space-xl) so a new section reads as a clear break, not just more
		   of the same. --section-space-xs was ~equal to --space-xl, flattening
		   the hierarchy; --section-space-s lifts the boundary one clear notch. */
		gap: var(--section-space-s);
		min-width: 0;
	}

	/* SECTION */
	.service-section {
		display: flex;
		flex-direction: column;
		/* Air between the header unit and the lists below it. */
		gap: var(--space-xl);
		scroll-margin-top: var(--svc-anchor-offset);
	}

	/* OPTIONAL BLOCK STYLE TOGGLES (Page Blocks). Each defaults to the plain
	   theme look when the field is unset; these modifiers only apply when an
	   editor opts in, so existing content is untouched. */

	/* Tinted background — a calm surface to separate a block from its
	   neighbours. Padding + radius give the tint breathing room; negative
	   scroll-margin keeps the TOC anchor aligned to the padded edge. */
	.service-section--tinted {
		padding: var(--space-xl);
		background-color: var(--surface-tinted);
		border-radius: var(--radius-m);
		scroll-margin-top: calc(var(--svc-anchor-offset) - var(--space-xl));
	}

	/* List-marker overrides for body lists. Default (check badge) is defined on
	   `.service-content .entry-content li` below; these swap it per-block. */
	.service-section--marker-dot .entry-content li::before {
		inline-size: 0.5em;
		block-size: 0.5em;
		margin-block-start: 0.55em;
		margin-inline-start: 0.4em;
		background-color: var(--primary);
	}
	.service-section--marker-dot .entry-content li::after,
	.service-section--marker-none .entry-content li::before,
	.service-section--marker-none .entry-content li::after {
		content: none;
	}
	.service-section--marker-none .entry-content li {
		padding-inline-start: 0;
	}

	/* Header rhythm is deliberately two-tier, not one gap doing two jobs:
	   the kicker is a LABEL that belongs to the title, so it hugs tight
	   (--space-2xs); the title→intro is a relationship CHANGE (display type
	   to body prose) and needs more air, added on the title's block-end below.
	   A single --space-xs for both left the body glued to the heading. */
	.service-section__head {
		display: flex;
		flex-direction: column;
		gap: var(--space-2xs);
	}

	/* Air between the title and the intro paragraph that follows it. Only
	   when an intro is actually present (`:has`), so a head with no intro
	   doesn't carry a trailing gap. */
	.service-section__head:has(.service-section__intro) .service-section__title {
		margin-block-end: var(--space-xs);
	}

	.service-section__kicker {
		margin: 0;
		font-size: var(--text-xs);
		font-weight: var(--weight-bold);
		letter-spacing: var(--tracking-caps);
		text-transform: uppercase;
		color: var(--secondary-active);
	}

	.service-section__title {
		margin: 0;
		font-family: var(--font-heading);
		font-size: var(--h3);
		font-weight: var(--weight-bold);
		line-height: var(--leading-tight);
		letter-spacing: var(--tracking-tight);
		color: var(--text-main);
	}

	/* page.css also loads on service singles (functions.php ~373) and brings its
	   own .entry-content rules: a 72ch cap and a child top-margin. Neither is
	   wanted here — this column deliberately owns its measure, and its rhythm
	   comes from gap, so the inherited margin stacked on top of it and
	   double-spaced every paragraph. Industry terms never load page.css, which
	   is why the same content read differently on the two templates. */
	.service-content .entry-content {
		max-inline-size: none;
	}

	.service-content .entry-content > * + * {
		margin-block-start: 0;
	}

	.service-section__intro {
		/* No measure cap — paragraphs fill the full content column and align
		   flush to the right gutter (deliberate; column reaches the gutter via
		   the 1fr grid above). wpautop emits sibling <p>/<ul> with no spacing of
		   their own — own the rhythm here with the contextual content gap. */
		display: flex;
		flex-direction: column;
		gap: var(--content-gap);
	}

	/* TWO-COLUMN block. Stacked by default (left above right on phones); splits
	   into two equal columns from the tablet breakpoint. Each column is a flex
	   stack so its optional heading and body carry the content gap. The column
	   gap uses --container-gap (the token for left-col ↔ right-col splits). */
	.service-two-col {
		display: grid;
		grid-template-columns: 1fr;
		gap: var(--container-gap);
	}

	.service-two-col__col {
		display: flex;
		flex-direction: column;
		gap: var(--content-gap);
		min-width: 0;
	}

	.service-two-col__col-title {
		font-size: var(--h4);
	}

	@media (min-width: 48em) {
		.service-two-col {
			grid-template-columns: 1fr 1fr;
		}
	}

	/* EVERY wysiwyg list in the content column gets the teal check-circle
	   treatment (matching .service-caplist), so prose lists read identically to
	   structured capability lists no matter which block or wrapper renders them.
	   Scoped to `.service-content` and doubled with `.entry-content` for the
	   specificity (0-3-1) needed to beat entry-content.css's
	   `.entry-content ul li { list-style: disc }` (0-2-1) — same @layer, so
	   specificity decides. The `.service-content` ancestor keeps it from
	   bleeding into sidebars/footers. */
	.service-content .entry-content ul,
	.service-content .entry-content ol {
		margin: 0;
		padding: 0;
		list-style: none;
		display: flex;
		flex-direction: column;
		/* Row gap must read LARGER than the intra-item line spacing
		   (line-height 1.5 ≈ 0.5em between wrapped lines) so two items never
		   blur into one. --content-gap (--space-m) clears that; a raw
		   --space-s did not, which read cramped on multi-line items. */
		gap: var(--content-gap);
	}

	.service-content .entry-content li {
		position: relative;
		list-style: none;
		padding-inline-start: calc(1.35em + var(--space-s));
		font-size: var(--text-m);
		line-height: var(--leading-normal);
		color: var(--text-body);
	}

	/* Teal check badge mirroring .service-caplist__marker: a tinted circle
	   (::before) + a tick masked in --primary on top (::after), both
	   token-driven (mask, not a coloured SVG, so the tick colour is --primary).
	   Absolutely positioned in the li's start padding; sized in em. */
	.service-content .entry-content li::before,
	.service-content .entry-content li::after {
		content: "";
		position: absolute;
		/* Centre the badge on the first line's cap-height, not the line-box
		   top. At line-height 1.5 the cap sits ~0.14em down; 0.075em left the
		   badge optically high against the text. */
		inset-block-start: 0.14em;
		inset-inline-start: 0;
		inline-size: 1.35em;
		block-size: 1.35em;
	}

	.service-content .entry-content li::before {
		border-radius: var(--radius-full);
		background-color: var(--primary-ultra-light);
	}

	.service-content .entry-content li::after {
		background-color: var(--primary);
		-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 0.8em 0.8em no-repeat;
		mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 0.8em 0.8em no-repeat;
	}

	.service-content .entry-content p {
		font-size: var(--text-m);
		line-height: var(--leading-relaxed);
		color: var(--text-body);
		/* Override the global 65ch cap (base.css .entry-content p) so service /
		   industry prose fills the content column to the right gutter. */
		max-inline-size: none;
	}

	/* SUB-HEADING RHYTHM inside prose. In-list group labels ("We also conduct",
	   "Ocular Bio-distribution") sat at the parent flex `gap: --content-gap`
	   from BOTH the group above and the list below — equidistant, so the eye
	   couldn't bind a label to its own list. A real heading gets MORE air above
	   (separating it from the previous group); the list right after it then
	   HUGS it (rule below) so label→list reads as one unit.

	   Heading TYPOGRAPHY (font, size, weight, line-height) is inherited from
	   the theme's global h1–h6 styles in base.css — the single source of truth,
	   so an editor H2 renders as a real H2 here just like everywhere else.
	   This rule only owns the heading's vertical rhythm in the content flow. */
	.service-content .entry-content :is(h2, h3, h4, h5, h6) {
		margin-block-start: var(--space-l);
		color: var(--text-main);
	}

	/* A heading that opens the section keeps the header's own spacing — no
	   double top-margin. */
	.service-content .entry-content > :first-child {
		margin-block-start: 0;
	}

	/* The list immediately after a heading hugs it — cancels half the parent
	   flex --content-gap so the label and its list read as a single unit
	   rather than two equidistant blocks. */
	.service-content .entry-content :is(h2, h3, h4, h5, h6) + :is(ul, ol) {
		margin-block-start: calc(var(--content-gap) * -0.5);
	}

	/* NUMBERED LISTS (ol) — the check badge is for bulleted lists; ordered
	   lists show a styled counter instead. Suppress the badge, draw a small-caps
	   primary number in the same start-padding slot via a CSS counter. */
	.service-content .entry-content ol {
		counter-reset: svc-ol;
	}
	.service-content .entry-content ol > li::before {
		content: counter(svc-ol) ".";
		counter-increment: svc-ol;
		display: flex;
		align-items: baseline;
		justify-content: flex-end;
		inline-size: 1.5em;
		block-size: auto;
		inset-block-start: 0;
		padding-inline-end: 0.1em;
		border-radius: 0;
		background: none;
		font-variant-numeric: tabular-nums;
		font-weight: var(--weight-semibold);
		color: var(--primary);
	}
	.service-content .entry-content ol > li::after {
		content: none;
	}
	.service-content .entry-content ol > li {
		padding-inline-start: calc(1.6em + var(--space-2xs));
	}

	/* 2-COLUMN LISTS — opt-in per Rich Text block. Items auto-balance across two
	   columns on wide viewports; collapses to one column when space is tight.
	   `break-inside: avoid` keeps a wrapped item from splitting across columns. */
	@media (min-width: 48em) {
		.service-section--list-2col .entry-content ul,
		.service-section--list-2col .entry-content ol {
			display: block;
			columns: 2;
			/* Was *2 — paired with a tight row gap it made the list read airy
			   sideways but cramped down the page (≈3:1 H:V ratio). Narrowed to
			   *1.5 so horizontal and vertical breathing room are balanced. */
			column-gap: calc(var(--container-gap) * 1.5);
		}
		/* CSS `columns` does NOT honour the flex `gap` set on the list above —
		   in column flow the vertical rhythm must come from item margin. 2-col
		   items wrap often (long capability names), so they need a clearly
		   larger row gap than single-col to keep wrapped items distinct.
		   Spacing goes on the BOTTOM (not top) so BOTH columns start flush at
		   the same baseline — a top margin would push column 2's first item
		   down by one gap and misalign the columns. */
		.service-section--list-2col .entry-content li {
			break-inside: avoid;
			margin-block-end: var(--content-gap);
		}
	}

	/* TABLES — token-styled, with a horizontal scroll on narrow viewports so a
	   wide table never breaks the layout. wpautop wraps block tables on their
	   own line; the scroll is provided by making the table's own box scrollable
	   via display:block + overflow on small screens. */
	.service-content .entry-content table {
		inline-size: 100%;
		border-collapse: collapse;
		font-size: var(--text-base);
		line-height: var(--leading-snug);
		color: var(--text-body);
	}
	.service-content .entry-content thead th,
	.service-content .entry-content tr > th {
		text-align: start;
		font-weight: var(--weight-semibold);
		color: var(--text-main);
		background-color: var(--surface-tinted);
	}
	.service-content .entry-content th,
	.service-content .entry-content td {
		padding: var(--space-xs) var(--space-s);
		border: 1px solid var(--border-default);
		vertical-align: top;
	}
	/* Mobile: let a wide table scroll horizontally inside its own box rather
	   than overflow the page. */
	@media (max-width: 47.99em) {
		.service-content .entry-content table {
			display: block;
			inline-size: max-content;
			max-inline-size: 100%;
			overflow-x: auto;
			-webkit-overflow-scrolling: touch;
		}
	}

	/* GROUPS — one column, always. Two tracks only worked while every group
	   held short capability chips; the moment one group carries a sentence and
	   its neighbour carries three words, the pair goes ragged and a hole opens
	   beside the taller one. Full width also matches how industry term pages
	   read, which is the behaviour we're standardising on. Short chip lists
	   still go two-up WITHIN a group via .service-group--cols-2 — that's the
	   editor's call, per list, where the content is known. */
	.service-groups {
		display: grid;
		grid-template-columns: 1fr;
		gap: var(--space-xl);
		align-items: start;
	}

	/* Editor opt-in, per section. Not a default: it only holds up when every
	   list is short and similar in length, and that's a judgement only the
	   person looking at the copy can make. */
	@media (min-width: 48em) {
		.service-groups--cols-2 {
			grid-template-columns: repeat(2, 1fr);
			column-gap: calc(var(--container-gap) * 1.5);
		}

		/* A list that flows across two columns needs both tracks to itself. */
		.service-groups--cols-2 .service-group--cols-2 {
			grid-column: 1 / -1;
		}
	}

	.service-group {
		display: flex;
		flex-direction: column;
		/* Title crowns its list with clear air below it so the hierarchy
		   reads (title above, items below) — separation between whole groups
		   still comes from the larger grid row gap. */
		gap: var(--space-m);
		min-width: 0;
	}

	/* A group that is the only child spans both columns (single long list
	   shouldn't squeeze into half-width). */
	.service-group:only-child {
		grid-column: 1 / -1;
	}

	.service-group__title {
		margin: 0;
		font-family: var(--font-heading);
		/* One true ramp step below the section title (--h4) so the parent→child
		   hierarchy reads on size alone. Was --h6, which skipped --h5 and left
		   the group titles reading as a much smaller, orphaned tier. */
		font-size: var(--h4);
		font-weight: var(--weight-bold);
		line-height: var(--leading-snug);
		letter-spacing: var(--tracking-tight);
		color: var(--text-main);
	}

	/* SECTION-LABEL group heading — the orange caps treatment, identical to the
	   block kicker (.service-section__kicker). Editor opt-in per group; these
	   are the groups that also join the on-page TOC. */
	.service-group__label {
		margin: 0;
		font-size: var(--text-xs);
		font-weight: var(--weight-bold);
		letter-spacing: var(--tracking-caps);
		text-transform: uppercase;
		color: var(--secondary-active);
	}

	/* Anchored labels (TOC targets) clear the sticky header on scroll-jump. */
	.service-group__label--anchor {
		scroll-margin-top: var(--svc-anchor-offset);
	}

	/* CAPABILITY LIST — borderless check + text, whitespace rhythm (no tiles,
	   no dividers). Quiet editorial treatment: the text leads, the teal check
	   is a light affordance, not a weighted tile. */
	.service-caplist {
		display: flex;
		flex-direction: column;
		/* Contextual content rhythm — matches the prose paragraph gap so the
		   list reads as part of the same content flow, not a tighter island. */
		gap: var(--content-gap);
		margin: 0;
		padding: 0;
		list-style: none;
	}

	/* 2-COLUMN GROUP — editor opt-in per group. Balances this group's checklist
	   across two columns; collapses to one when space is tight. This is the only
	   place two columns still happen, and it's deliberate: the editor opts in
	   per list, knowing the items are short enough to take it.
	   Mirrors the Rich Text block's --list-2col behaviour. */
	@media (min-width: 48em) {
		.service-group--cols-2 .service-caplist {
			display: block;
			columns: 2;
			column-gap: calc(var(--container-gap) * 1.5);
		}
		/* In column flow flex `gap` is ignored — vertical rhythm comes from
		   item margin. Bottom margin (not top) so both columns start flush. */
		.service-group--cols-2 .service-caplist__item {
			break-inside: avoid;
			margin-block-end: var(--space-m);
		}
	}

	.service-caplist__item {
		display: flex;
		align-items: flex-start;
		gap: var(--space-s);
		margin: 0;
		/* Reading-body step (--text-m) so capability lists sit in lock-step with
		   the paragraphs above them AND the wysiwyg lists in the Page Content
		   block — one list size site-wide. The check sizes in `em` off this. */
		font-size: var(--text-m);
		line-height: var(--leading-normal);
	}

	/* Soft circular badge (light-teal fill + teal tick) — reads as "verified
	   capability" while staying quiet so the text leads; the solid-teal fill
	   was too heavy down a long list. Sized in em so the whole badge tracks
	   the list text; optically centred on the first line. */
	.service-caplist__marker {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		flex: 0 0 auto;
		inline-size: 1.35em;
		block-size: 1.35em;
		/* Centre the badge on the first line's cap-height (not the line-box
		   top). 0.14em matches the Page Content (.entry-content li) badge offset
		   exactly, so the two list systems align tick-for-tick. */
		margin-block-start: 0.14em;
		border-radius: var(--radius-full);
		background: var(--primary-ultra-light);
		color: var(--primary);
	}

	/* Icon-framework behaviour (block, no shrink) but EM-sized — the framework
	   .icon-* classes are all fixed-rem, which can't track text. The tick must
	   scale with the badge, so dimensions stay in em while base behaviour
	   matches the framework. */
	.service-caplist__icon {
		display: block;
		flex-shrink: 0;
		inline-size: 0.8em;
		block-size: 0.8em;
	}

	.service-caplist__text {
		font-weight: var(--weight-regular);
		line-height: var(--leading-normal);
		color: var(--text-body);
	}

	/* In-list LABEL row (a "## " line) — a plain caption inside the checklist,
	   no marker, flush to the list's start edge. Sits a touch heavier than the
	   items so it reads as a quiet sub-caption above the ticks that follow.
	   A label that isn't the first row gets a little air above to separate it
	   from the items it closes. */
	.service-caplist__item--label {
		display: block;
	}
	.service-caplist__item--label + .service-caplist__item--label,
	.service-caplist__item:not(.service-caplist__item--label) + .service-caplist__item--label {
		padding-block-start: var(--space-xs);
	}
	.service-list__label {
		font-weight: var(--weight-semibold);
		line-height: var(--leading-snug);
		color: var(--text-main);
	}

	/* PER-GROUP BULLET STYLE — overrides the default check badge for one group.
	   Mirrors the block-level marker toggles but scoped to .service-caplist's
	   own SVG badge (not the .entry-content ::before/::after mask).
	   Dot: shrink the badge to a small solid primary dot, hide the tick. */
	.service-group--marker-dot .service-caplist__marker {
		inline-size: 0.5em;
		block-size: 0.5em;
		margin-block-start: 0.5em;
		background: var(--primary);
	}
	.service-group--marker-dot .service-caplist__icon {
		display: none;
	}
	/* None: drop the marker entirely and reclaim its space so the text aligns
	   to the group's start edge. */
	.service-group--marker-none .service-caplist__marker {
		display: none;
	}

	/* PER-GROUP TINTED BACKGROUND — a soft panel behind one group only, to set
	   it apart from its neighbours. Same surface + radius language as the
	   block-level --tinted modifier. */
	.service-group--tinted {
		padding: var(--space-l);
		background-color: var(--surface-tinted);
		border-radius: var(--radius-m);
	}

	/* ACCREDITATION STRIP — inline trust band (structural rules, not
	   per-row decoration). Label left, chips right; stacks on narrow. */
	.service-accred {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		justify-content: space-between;
		gap: var(--space-m) var(--space-l);
		padding-block: var(--space-l);
		border-block: var(--divider);
		scroll-margin-top: var(--svc-anchor-offset);
	}

	.service-accred__label {
		margin: 0;
		font-size: var(--text-xs);
		font-weight: var(--weight-bold);
		letter-spacing: var(--tracking-caps);
		text-transform: uppercase;
		color: var(--secondary-active);
	}

	.service-accred__list {
		display: flex;
		flex-wrap: wrap;
		gap: var(--space-xs);
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.service-accred__chip {
		display: inline-flex;
		align-items: center;
		padding: var(--space-xs) var(--space-m);
		border-radius: var(--radius-m);
		background: var(--surface-raised);
		border: var(--card-border);
		font-size: var(--text-s);
		font-weight: var(--weight-semibold);
		letter-spacing: var(--tracking-snug);
		color: var(--text-muted);
	}

	/* EDITORIAL RELATED SERVICES — stacked image-left cards (matches the v1
	   "Related Services" mobile/list design): square thumbnail left, title +
	   optional descriptor, arrow far right. Each item is a bordered white card.
	   Same shape on desktop and mobile — only the thumb scales down. */
	.service-related {
		display: flex;
		flex-direction: column;
		gap: var(--space-l);
		scroll-margin-top: var(--svc-anchor-offset);
	}

	.service-section__kicker--alt {
		color: var(--secondary-active);
	}

	.service-related__list {
		display: flex;
		flex-direction: column;
		gap: var(--card-gap);
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.service-related__item {
		margin: 0;
		min-width: 0;
	}

	.service-related__link {
		display: flex;
		align-items: center;
		gap: var(--space-m);
		padding: var(--space-2xs);
		text-decoration: none;
		color: inherit;
		background-color: var(--surface-raised);
		border: 1px solid var(--border-subtle);
		border-radius: var(--card-radius);
		transition: border-color var(--duration-fast) var(--ease-default),
			box-shadow var(--duration-fast) var(--ease-default);
	}

	.service-related__media {
		flex: 0 0 auto;
		inline-size: 4.5rem;
		block-size: 4.5rem;
		overflow: hidden;
		border-radius: var(--radius-s);
		background-color: var(--surface-tinted);
	}

	.service-related__media img {
		inline-size: 100%;
		block-size: 100%;
		object-fit: cover;
		display: block;
		transition: transform var(--card-transition);
	}

	.service-related__media--placeholder {
		background-color: var(--primary-ultra-light);
	}

	.service-related__text {
		display: flex;
		flex-direction: column;
		gap: var(--space-3xs);
		min-width: 0;
		flex: 1 1 auto;
	}

	.service-related__name {
		font-family: var(--font-body);
		font-size: var(--text-m);
		font-weight: var(--weight-regular);
		line-height: var(--leading-snug);
		color: var(--text-main);
		transition: color var(--duration-fast) var(--ease-default);
	}

	@media (min-width: 48em) {
		.service-related__list {
			max-inline-size: 65ch;
		}

		.service-related__media {
			inline-size: 4rem;
			block-size: 4rem;
		}
	}

	/* Quiet inline arrow — muted at rest, slides + goes full primary on hover. */
	.service-related__arrow {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		flex: 0 0 auto;
		padding-inline-end: var(--space-2xs);
		color: var(--text-muted);
		transition: color var(--duration-fast) var(--ease-default),
			transform var(--duration-fast) var(--ease-default);
	}

	.service-related__arrow .icon-btn-arrow {
		inline-size: var(--icon-inline-l);
		block-size: var(--icon-inline-l);
	}

	@media (hover: hover) {
		.service-related__link:hover {
			border-color: var(--primary-light);
			box-shadow: var(--card-shadow);
		}

		.service-related__link:hover .service-related__name {
			color: var(--primary);
		}

		.service-related__link:hover .service-related__media img {
			transform: scale(1.04);
		}

		.service-related__link:hover .service-related__arrow {
			color: var(--primary);
			transform: translateX(var(--space-2xs));
		}
	}

	.service-related__link:active .service-related__name,
	.service-related__link:active .service-related__arrow {
		color: var(--primary);
	}

	.service-related__link:focus-visible {
		outline: var(--focus-ring);
		outline-offset: var(--focus-ring-offset);
	}

	/* Incremental View More — pill button mirroring the canonical
	   related-services component. Drives IIFE 42 via the
	   data-view-more-incremental contract on the list above. Styled here (not
	   reusing related-services.css) because that sheet isn't enqueued on
	   service singles, whereas this one loads on both service + industry. */
	.service-related__view-more {
		display: inline-flex;
		align-items: center;
		gap: var(--space-2xs);
		inline-size: fit-content;
		margin-block-start: var(--content-gap);
		padding-block: var(--space-2xs);
		padding-inline: var(--space-m);
		background: transparent;
		border: 1px solid var(--border-default);
		border-radius: var(--radius-full);
		color: var(--primary);
		font-family: var(--font-body);
		font-size: var(--text-s);
		font-weight: var(--weight-semibold);
		cursor: pointer;
		transition: background-color var(--duration-fast) var(--ease-default),
			border-color var(--duration-fast) var(--ease-default);
	}

	.service-related__view-more strong {
		color: var(--primary-ultra-dark);
		font-weight: var(--weight-bold);
	}

	@media (hover: hover) {
		.service-related__view-more:hover {
			background: var(--primary-ultra-light);
			border-color: var(--primary-light);
		}
	}

	.service-related__view-more:active {
		background: var(--primary-ultra-light);
	}

	.service-related__view-more:focus-visible {
		outline: var(--focus-ring);
		outline-offset: var(--focus-ring-offset);
	}

	.service-related__view-more-icon {
		flex-shrink: 0;
		inline-size: var(--icon-inline-s);
		block-size: var(--icon-inline-s);
		color: currentColor;
	}
}
