/* ==========================================================================
   laravel-cms content kinds — the core stylesheet (DEV-140 step 22).

   Copied to public/assets/cms/css/content-kinds.css by core:update and
   linked once from cms::presence.blocks and the CMS page view through
   @push('head_css'), which the head renders BEFORE styles.css and the
   branding stylesheet — so the branding sheet, the admin's last word, is
   last, and a presence's custom-css needs no specificity contest.

   Every value the four demo residuals had to override reads a custom
   property with today's literal as its fallback: the shared
   `--content-*` properties come from the content.bands group, the
   per-kind ones from each kind's brandSettings(), the button and heading
   properties from the portal's own settings. A select setting's choice
   arrives as a class on the block's root, `cms-<setting>-<value>`
   (ContentBlockService::renderStructured()); a per-block ground is
   `cms-kind--tone-<tone>` and `cms-kind--bleed-<bleed>`. Blank everywhere
   draws exactly what the former inline <style> drew.
   ========================================================================== */

/* ---- Shared: colour, prose, links, eyebrow, lists, tables ---------------- */

.cms-kind { color: var(--content-text-colour, #111827); }
.cms-kind__prose { line-height: var(--content-body-line-height, var(--content-line-height, 1.65)); }
.cms-kind__prose > * { margin: 0; }
.cms-kind__prose > * + * { margin-top: var(--content-paragraph-spacing, 0.9rem); }
.cms-kind__prose a {
    color: var(--content-link-colour, var(--brand-secondary-colour, inherit));
    font-weight: var(--content-link-weight, inherit);
    text-decoration: underline;
    text-decoration-thickness: var(--content-link-underline-width, auto);
}
.cms-content-link-underline-none .cms-kind__prose a,
.cms-brochure.cms-content-link-underline-none .cms-kind__prose a { text-decoration: none; }
.cms-kind__prose ul, .cms-kind__prose ol { padding-left: 1.35rem; }

/* Lists inside kinds, by content-list-style: ruled rows, ticks, dashes or chips. */
.cms-content-list-style-ruled .cms-kind__prose ul,
.cms-content-list-style-ticks .cms-kind__prose ul,
.cms-content-list-style-dashes .cms-kind__prose ul,
.cms-content-list-style-chips .cms-kind__prose ul,
.cms-content-list-style-squares .cms-kind__prose ul,
.cms-content-list-style-tick-discs .cms-kind__prose ul { list-style: none; padding-left: 0; }
/* The rows' rule and the markers' colour (step 29b): the ruled rows were a
   fixed 1px content-border hairline and every marker the primary colour. */
.cms-content-list-style-ruled .cms-kind__prose li,
.cms-content-list-style-squares .cms-kind__prose li { padding: 0.5rem 0;
    border-bottom: var(--content-list-rule-width, 1px) solid var(--content-list-rule-colour, var(--content-border-colour, #e5e7eb)); }
.cms-content-list-style-ticks .cms-kind__prose li,
.cms-content-list-style-dashes .cms-kind__prose li,
.cms-content-list-style-squares .cms-kind__prose li { position: relative; padding-left: 1.5rem; }
.cms-content-list-style-ticks .cms-kind__prose li::before { content: '\2713'; position: absolute; left: 0; color: var(--content-list-marker-colour, var(--brand-primary-colour, #691EDA)); font-weight: 700; }
.cms-content-list-style-dashes .cms-kind__prose li::before { content: '\2014'; position: absolute; left: 0; color: var(--content-list-marker-colour, var(--brand-primary-colour, #691EDA)); }
/* Squares: ruled rows, each marked with a solid square. */
.cms-content-list-style-squares .cms-kind__prose li::before { content: ''; position: absolute; left: 0; top: calc(0.5rem + 0.45em); width: 0.7rem; height: 0.7rem;
    background: var(--content-list-marker-colour, var(--brand-primary-colour, #691EDA)); }
/* Tick discs: a white tick in a filled disc. */
.cms-content-list-style-tick-discs .cms-kind__prose li { position: relative; padding-left: 1.9rem; }
.cms-content-list-style-tick-discs .cms-kind__prose li + li { margin-top: 0.5rem; }
.cms-content-list-style-tick-discs .cms-kind__prose li::before { content: ''; position: absolute; left: 0; top: 0.2em; width: 1.25rem; height: 1.25rem; border-radius: 50%;
    background: var(--content-list-marker-colour, var(--brand-primary-colour, #691EDA)) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 12.5l4 4 8-9'/%3E%3C/svg%3E") center / 70% no-repeat; }
.cms-content-list-style-chips .cms-kind__prose ul { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.cms-content-list-style-chips .cms-kind__prose li { padding: 0.25rem 0.75rem; border-radius: 9999px; font-size: 0.9375rem;
    background: color-mix(in srgb, var(--brand-primary-colour, #691EDA) 10%, transparent); }

/* Tables inside Text blocks, by content-table-style / content-table-emphasis.
   The rule width and colour, the type size, the cell padding, the header
   cells' ground and text and the emphasis colour are settings (step 29b):
   each was a literal a style fixed. */
.cms-kind__prose table { font-size: var(--content-table-size, inherit); }
.cms-kind__prose th { background: var(--content-table-head-bg, transparent); color: var(--content-table-head-text, inherit); }
.cms-content-table-style-ruled .cms-kind__prose table { width: 100%; border-collapse: collapse; border-top: calc(2 * var(--content-table-rule-width, 1px)) solid var(--content-table-rule-colour, currentColor); }
.cms-content-table-style-ruled .cms-kind__prose th,
.cms-content-table-style-ruled .cms-kind__prose td { padding: var(--content-table-cell-padding, 0.75rem 0.5rem);
    border-bottom: var(--content-table-rule-width, 1px) solid var(--content-table-rule-colour, var(--content-border-colour, #e5e7eb)); text-align: left; }
.cms-content-table-style-card .cms-kind__prose table { width: 100%; border-collapse: separate; border-spacing: 0; border-radius: var(--radius-panel, 0.75rem);
    overflow: hidden; box-shadow: 0 8px 24px rgba(10, 10, 10, 0.08); background: var(--content-bg-colour, #fff); }
.cms-content-table-style-card .cms-kind__prose th,
.cms-content-table-style-card .cms-kind__prose td { padding: var(--content-table-cell-padding, 0.875rem 1rem); text-align: left;
    border-bottom: var(--content-table-rule-width, 1px) solid var(--content-table-rule-colour, var(--content-border-colour, #e5e7eb)); }
.cms-content-table-style-card .cms-kind__prose th { font-family: var(--header-font-family, inherit); }
.cms-content-table-style-plain .cms-kind__prose th,
.cms-content-table-style-plain .cms-kind__prose td { padding: var(--content-table-cell-padding, 0.5rem 0.5rem 0.5rem 0); border: 0; text-align: left; }
.cms-content-table-emphasis-last-column .cms-kind__prose tr > :last-child { font-weight: 700; color: var(--content-table-emphasis-colour, var(--brand-primary-colour, #691EDA)); }
.cms-content-table-emphasis-last-column .cms-kind__prose thead tr > :last-child { color: var(--content-table-head-text, var(--content-table-emphasis-colour, var(--brand-primary-colour, #691EDA))); }
.cms-content-table-emphasis-numeric .cms-kind__prose td { font-variant-numeric: tabular-nums; }

/* Eyebrow: tracked text, or a pill by content-eyebrow-style. */
.cms-kind__eyebrow { margin: 0 0 var(--content-eyebrow-space, 0.625rem); font-size: var(--content-eyebrow-size, 0.75rem);
    font-weight: var(--content-eyebrow-weight, 700); letter-spacing: var(--content-eyebrow-letter-spacing, 0.14em);
    text-transform: var(--content-eyebrow-transform, uppercase); color: var(--content-eyebrow-colour, var(--brand-primary-colour, #691EDA)); }
/* `small-caps` is a font variant, not a text transform, so the choice that
   cannot be substituted into the property above is drawn by its class. */
.cms-content-eyebrow-transform-small-caps .cms-kind__eyebrow { text-transform: none; font-variant: small-caps; }
.cms-content-eyebrow-style-pill .cms-kind__eyebrow { display: inline-block; padding: var(--content-eyebrow-padding, 0.3rem 0.8rem); border-radius: 9999px;
    background: var(--content-eyebrow-bg, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 12%, transparent)); }

/* ---- Section headings inside kinds ------------------------------------- */

/* The heading's own margins: `section-heading-margin-top` / `-bottom` are
   emitted by laravel-ui but, outside the docs view, no rule read them — so a
   kind's heading had no space under it and every demo wrote one (DEV-145,
   Residual 34). Blank is 0, which is what the preflight leaves and what the
   heading drew before. */
.cms-kind .cms-system-section__heading {
    margin-top: var(--section-heading-margin-top, 0);
    margin-bottom: var(--section-heading-margin-bottom, 0);
    line-height: var(--content-kind-heading-line-height, inherit);
    text-align: var(--content-kind-heading-align, start);
}
/* A Text band's heading is named with the kind headings (step 29b): the
   brochure root carries the shared choice, so the Text band follows it. */
.cms-content-kind-heading-align-centre .cms-system-section__heading,
.cms-content-kind-heading-align-centre .cms-brochure__heading { text-align: center; }
/* A Text band's heading is a plain <h2>, not a ui-heading (Residual 39), so it
   is named here too — the one shared heading treatment it can follow. */
.cms-content-kind-heading-decoration-left-rule .cms-brochure__heading,
.cms-content-kind-heading-decoration-left-rule .cms-system-section__heading {
    border-left: var(--content-kind-heading-decoration-width, 0.5rem) solid var(--content-kind-heading-decoration-colour, var(--brand-primary-colour, #691EDA)); padding-left: 1rem; }
.cms-content-kind-heading-decoration-underline-rule .cms-brochure__heading::after,
.cms-content-kind-heading-decoration-underline-rule .cms-system-section__heading::after {
    content: ''; display: block; width: var(--content-kind-heading-decoration-length, 4rem); height: var(--content-kind-heading-decoration-width, 3px); margin-top: 0.75rem;
    background: var(--content-kind-heading-decoration-colour, var(--brand-primary-colour, #691EDA)); }
.cms-content-kind-heading-align-centre.cms-content-kind-heading-decoration-underline-rule .cms-system-section__heading::after,
.cms-content-kind-heading-align-centre.cms-content-kind-heading-decoration-underline-rule .cms-brochure__heading::after { margin-inline: auto; }
/* A heading alignment per kind (step 29b): the shared choice above is one
   for every kind, but a site centres its figures' heading and hangs its
   split's left, say. The kind's root carries both classes, and these come
   later at the same weight, so the kind's own choice wins. */
.cms-content-cards-heading-align-left .cms-system-section__heading, .cms-content-stats-heading-align-left .cms-system-section__heading,
.cms-content-split-heading-align-left .cms-system-section__heading, .cms-content-quotes-heading-align-left .cms-system-section__heading { text-align: left; }
.cms-content-cards-heading-align-centre .cms-system-section__heading, .cms-content-stats-heading-align-centre .cms-system-section__heading,
.cms-content-split-heading-align-centre .cms-system-section__heading, .cms-content-quotes-heading-align-centre .cms-system-section__heading { text-align: center; }
.cms-content-kind-heading-decoration-underline-rule:is(.cms-content-cards-heading-align-left, .cms-content-stats-heading-align-left, .cms-content-split-heading-align-left, .cms-content-quotes-heading-align-left) .cms-system-section__heading::after { margin-inline: 0; }
.cms-content-kind-heading-decoration-underline-rule:is(.cms-content-cards-heading-align-centre, .cms-content-stats-heading-align-centre, .cms-content-split-heading-align-centre, .cms-content-quotes-heading-align-centre) .cms-system-section__heading::after { margin-inline: auto; }

/* ---- Grounds: tone and bleed ------------------------------------------- */

/* A block's ground. The tone paints the kind's root as a panel inside the
   measure; on a full-bleed band the wrapper paints it edge to edge instead
   (below). Blank keeps the block on the page as it draws today. */
.cms-kind--tone-panel, .cms-kind--tone-tint, .cms-kind--tone-ink, .cms-kind--tone-brand, .cms-kind--tone-image {
    padding: var(--content-band-padding, 2.5rem 2.25rem); border-radius: var(--radius-panel, 1rem); }
.cms-kind--tone-panel { background: var(--content-tone-panel-bg, var(--content-bg-colour, #fff)); color: var(--content-tone-panel-text, var(--content-text-colour, #111827)); }
.cms-kind--tone-tint { background: var(--content-tone-tint-bg, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 8%, var(--content-bg-colour, #fff)))); color: var(--content-tone-tint-text, inherit); }
.cms-kind--tone-ink { background: var(--content-tone-ink-bg, var(--brand-ink, #1d1b22)); color: var(--content-tone-ink-text, #fff); }
.cms-kind--tone-brand { background: var(--content-tone-brand-bg, var(--brand-primary-colour, #691EDA)); color: var(--content-tone-brand-text, var(--text-primary-colour, #fff)); }
.cms-kind--tone-image { color: #fff; background-color: var(--brand-ink, #1d1b22); background-size: cover; background-position: center;
    background-image: linear-gradient(rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.45)), var(--cms-band-image); }

/* Bugs 1: on a dark ground a kind and its headings inherit, so nothing paints
   the portal's header or content colour on ink. */
.cms-kind--tone-ink, .cms-kind--tone-brand, .cms-kind--tone-image, .cms-hero--dark,
.cms-kind--tone-ink :is(h1, h2, h3, h4, .cms-system-section__heading, .ui-heading),
.cms-kind--tone-brand :is(h1, h2, h3, h4, .cms-system-section__heading, .ui-heading),
.cms-kind--tone-image :is(h1, h2, h3, h4, .cms-system-section__heading, .ui-heading),
.cms-hero--dark :is(h1, h2, h3, h4, .ui-heading) { color: inherit; }
/* A kind draws its heading with <x-ui::heading variant="section">, whose own
   rule in styles.css is 0-2-0 and lands after this sheet — so the two above
   tie and the portal's heading colour wins, charcoal on a charcoal band. One
   class more, and the tone's own colour holds. */
.cms-kind.cms-kind--tone-ink :is(.ui-heading, .cms-system-section__heading),
.cms-kind.cms-kind--tone-brand :is(.ui-heading, .cms-system-section__heading),
.cms-kind.cms-kind--tone-image :is(.ui-heading, .cms-system-section__heading),
.cms-hero.cms-hero--dark .ui-heading { color: inherit; }
.cms-kind--tone-ink .cms-kind__prose a, .cms-kind--tone-brand .cms-kind__prose a, .cms-kind--tone-image .cms-kind__prose a { color: inherit; }
/* The eyebrow on a dark ground is the ground's text at 85% — unless the
   eyebrow has a colour of its own, which it keeps at full strength (step 29b:
   an opacity here dimmed, and the colour overrode, content-eyebrow-colour). */
.cms-kind--tone-ink .cms-kind__eyebrow, .cms-kind--tone-brand .cms-kind__eyebrow, .cms-kind--tone-image .cms-kind__eyebrow {
    color: var(--content-eyebrow-colour, color-mix(in srgb, currentColor 85%, transparent)); }

/* The brochure's bands (cms::presence.blocks). A band with a tone paints the
   same ground as its block; on `bleed: full` the band runs edge to edge and
   the block inside is held to the band measure (Residual 1). */
.cms-brochure__band--tone-panel { background: var(--content-tone-panel-bg, var(--content-bg-colour, #fff)); color: var(--content-tone-panel-text, var(--content-text-colour, #111827)); }
.cms-brochure__band--tone-tint { background: var(--content-tone-tint-bg, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 8%, var(--content-bg-colour, #fff)))); color: var(--content-tone-tint-text, inherit); }
.cms-brochure__band--tone-ink { background: var(--content-tone-ink-bg, var(--brand-ink, #1d1b22)); color: var(--content-tone-ink-text, #fff); }
.cms-brochure__band--tone-brand { background: var(--content-tone-brand-bg, var(--brand-primary-colour, #691EDA)); color: var(--content-tone-brand-text, var(--text-primary-colour, #fff)); }
/* content-tone-image-attachment: fixed (DEV-167) — the picture stays while
   the page slides over it. Dropped for a visitor who asked for less motion,
   and on touch, where a fixed background is a known repaint trap. */
/* The choice class rides on the block's own root AND on the brochure root,
   so the block matches it on itself and the band as a descendant. */
.cms-kind--tone-image.cms-content-tone-image-attachment-fixed,
.cms-content-tone-image-attachment-fixed .cms-brochure__band--tone-image { background-attachment: fixed; }
@media (prefers-reduced-motion: reduce), (hover: none) {
    .cms-kind--tone-image.cms-content-tone-image-attachment-fixed,
    .cms-content-tone-image-attachment-fixed .cms-brochure__band--tone-image { background-attachment: scroll; }
}
.cms-brochure__band--tone-image { color: #fff; background-color: var(--brand-ink, #1d1b22); background-size: cover; background-position: center;
    background-image: linear-gradient(rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.45)), var(--cms-band-image); }
.cms-brochure__band--bleed-full { width: auto; max-width: none; margin-inline: 0;
    padding: var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem)); }
.cms-brochure__band--bleed-full > * { max-width: var(--content-band-measure, var(--content-max-width, 1280px)); margin-inline: auto; }
/* Inside a toned band the block's own ground gives way to the band's. */
/* Not a call to action (step 29b): its tone paints its own slab, which keeps
   its ground and padding inside the band as an untoned one does. On an image
   band it still gives way, or the slab would hide the picture. */
.cms-brochure__band--bleed-full > .cms-kind--tone-panel:not(.cms-band), .cms-brochure__band--bleed-full > .cms-kind--tone-tint:not(.cms-band),
.cms-brochure__band--bleed-full > .cms-kind--tone-ink:not(.cms-band), .cms-brochure__band--bleed-full > .cms-kind--tone-brand:not(.cms-band),
.cms-brochure__band--bleed-full > .cms-kind--tone-image { background: transparent; padding: 0; border-radius: 0; }

/* A measure per kind (Residual 35). `content-band-measure` is one width for
   the whole site, but a site reads at two or three: figures wider than the
   prose, an FAQ narrower than the cards. Each kind's band holds its block to
   its own, blank keeping today's — nothing on a band inside the measure, the
   band measure on one that bleeds. These sit before the self-grounded hero's
   fill rule below, which is the one block that must reach the band's edge. */
.cms-brochure__band--hero > * { max-width: var(--content-hero-band-measure, none); }
.cms-brochure__band--hero.cms-brochure__band--bleed-full > * { max-width: var(--content-hero-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--cards > * { max-width: var(--content-cards-band-measure, none); }
.cms-brochure__band--cards.cms-brochure__band--bleed-full > * { max-width: var(--content-cards-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--stats > * { max-width: var(--content-stats-band-measure, none); }
.cms-brochure__band--stats.cms-brochure__band--bleed-full > * { max-width: var(--content-stats-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--steps > * { max-width: var(--content-steps-band-measure, none); }
.cms-brochure__band--steps.cms-brochure__band--bleed-full > * { max-width: var(--content-steps-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--split > * { max-width: var(--content-split-band-measure, none); }
.cms-brochure__band--split.cms-brochure__band--bleed-full > * { max-width: var(--content-split-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--quotes > * { max-width: var(--content-quotes-band-measure, none); }
.cms-brochure__band--quotes.cms-brochure__band--bleed-full > * { max-width: var(--content-quotes-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--faq > * { max-width: var(--content-faq-band-measure, none); }
.cms-brochure__band--faq.cms-brochure__band--bleed-full > * { max-width: var(--content-faq-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--callout > * { max-width: var(--content-callout-band-measure, none); }
.cms-brochure__band--callout.cms-brochure__band--bleed-full > * { max-width: var(--content-callout-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--band > * { max-width: var(--content-band-cta-band-measure, none); }
.cms-brochure__band--band.cms-brochure__band--bleed-full > * { max-width: var(--content-band-cta-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
.cms-brochure__band--text > * { max-width: var(--content-text-band-measure, none); }
.cms-brochure__band--text.cms-brochure__band--bleed-full > * { max-width: var(--content-text-band-measure, var(--content-band-measure, var(--content-max-width, 1280px))); margin-inline: auto; }
/* A Text band's prose keeps its own reading measure (Residual 24) inside the
   band's: the band measure holds the heading and any table, the reading one
   the paragraphs. Stated here, after the rule above, because the body is a
   direct child of the band and would otherwise take the band's width. */
.cms-brochure__band--text > .cms-brochure__body { max-width: var(--content-reading-measure, var(--content-text-band-measure, none)); }
.cms-brochure__band--text.cms-brochure__band--bleed-full > .cms-brochure__body { max-width: var(--content-reading-measure, var(--content-text-band-measure, var(--content-band-measure, var(--content-max-width, 1280px)))); margin-inline: auto; }

/* A hero that paints its own ground — a dark variant, or a background image —
   must reach the band's edges rather than stop at the measure like ordinary
   content, or the band bleeds and the hero does not. It fills the band and
   holds its copy to the measure with padding instead of width, so its grid
   keeps its columns. A hero that draws as a panel keeps its panel, and a
   toned one is the band's own ground, padded already. Two classes, so a
   presence can say otherwise. */
.cms-brochure__band--bleed-full > .cms-hero:where(.cms-hero--dark, .cms-hero--with-background):where(:not(.cms-kind--tone-panel), :not(.cms-kind--tone-tint)) {
    max-width: none; margin-inline: 0; border-radius: 0;
    padding-inline: max(var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem)), calc((100% - var(--content-band-measure, var(--content-max-width, 1280px))) / 2));
}
.cms-brochure__band--bleed-full > .cms-kind--tone-ink, .cms-brochure__band--bleed-full > .cms-kind--tone-brand,
.cms-brochure__band--bleed-full > .cms-kind--tone-image { background-image: none; }
/* A brochure holding a full-bleed band spaces its bands by padding rather
   than a gap, so toned bands butt against their neighbours (three classes:
   the base presence sheet's own brochure rule weighs two). */
.cms-brochure.cms-brochure--bleeds, .presence--base .cms-brochure.cms-brochure--bleeds { gap: 0; padding-block: 0; }
.cms-brochure--bleeds .cms-brochure__band { padding-block: calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2); }
.cms-brochure--bleeds .cms-brochure__band--bleed-full { padding-block: var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)); }

/* The space a kind's band takes (the brief's "the kind's own padding"). Every
   demo sets at least one band tighter or looser than the rest — a hero that
   paints itself edge to edge wants none, a stats strip half the rest. Blank is
   what the band takes today: nothing inside a gap-spaced brochure, half the
   band gap in one that bleeds, the band padding and gutter on a band that
   bleeds. It is the whole padding, not the block alone, so a kind can pull its
   band in to the edges (a hero that paints its own ground) or hold it off them
   (a framed call to action) as well as set its rhythm. */
.cms-brochure__band--hero:not(.cms-brochure__band--bleed-full) { padding: var(--content-hero-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--hero:not(.cms-brochure__band--bleed-full) { padding: var(--content-hero-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--hero.cms-brochure__band--bleed-full { padding: var(--content-hero-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--cards:not(.cms-brochure__band--bleed-full) { padding: var(--content-cards-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--cards:not(.cms-brochure__band--bleed-full) { padding: var(--content-cards-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--cards.cms-brochure__band--bleed-full { padding: var(--content-cards-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--stats:not(.cms-brochure__band--bleed-full) { padding: var(--content-stats-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--stats:not(.cms-brochure__band--bleed-full) { padding: var(--content-stats-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--stats.cms-brochure__band--bleed-full { padding: var(--content-stats-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--steps:not(.cms-brochure__band--bleed-full) { padding: var(--content-steps-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--steps:not(.cms-brochure__band--bleed-full) { padding: var(--content-steps-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--steps.cms-brochure__band--bleed-full { padding: var(--content-steps-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--split:not(.cms-brochure__band--bleed-full) { padding: var(--content-split-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--split:not(.cms-brochure__band--bleed-full) { padding: var(--content-split-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--split.cms-brochure__band--bleed-full { padding: var(--content-split-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--quotes:not(.cms-brochure__band--bleed-full) { padding: var(--content-quotes-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--quotes:not(.cms-brochure__band--bleed-full) { padding: var(--content-quotes-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--quotes.cms-brochure__band--bleed-full { padding: var(--content-quotes-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--faq:not(.cms-brochure__band--bleed-full) { padding: var(--content-faq-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--faq:not(.cms-brochure__band--bleed-full) { padding: var(--content-faq-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--faq.cms-brochure__band--bleed-full { padding: var(--content-faq-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--callout:not(.cms-brochure__band--bleed-full) { padding: var(--content-callout-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--callout:not(.cms-brochure__band--bleed-full) { padding: var(--content-callout-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--callout.cms-brochure__band--bleed-full { padding: var(--content-callout-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--band:not(.cms-brochure__band--bleed-full) { padding: var(--content-band-cta-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--band:not(.cms-brochure__band--bleed-full) { padding: var(--content-band-cta-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--band.cms-brochure__band--bleed-full { padding: var(--content-band-cta-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }
.cms-brochure__band--text:not(.cms-brochure__band--bleed-full) { padding: var(--content-text-band-padding, 0 0); }
.cms-brochure--bleeds .cms-brochure__band--text:not(.cms-brochure__band--bleed-full) { padding: var(--content-text-band-padding, calc(var(--content-band-gap, calc(4 * var(--page-content-gap, 1rem))) / 2) 0); }
.cms-brochure__band--text.cms-brochure__band--bleed-full { padding: var(--content-text-band-padding, var(--content-band-padding, clamp(2.5rem, 6vw, 5rem)) var(--content-band-gutter, clamp(1.25rem, 5vw, 4rem))); }

/* Text blocks: the reading measure inside the band (Residual 24), a drop cap (Residual 23). */
.cms-brochure__body { max-width: var(--content-reading-measure, none); }
/* A Text band's own alignment (DEV-167). The measure keeps its place: a
   centred band is centred text on the same column, not a wider one. */
.cms-brochure__band--align-left { text-align: left; }
.cms-brochure__band--align-centre { text-align: center; }
.cms-brochure__band--align-centre :is(.cms-brochure__body, .cms-system-section__body) { margin-inline: auto; }
.cms-brochure__band--drop-cap .cms-brochure__body > p:first-child::first-letter {
    float: left; font-size: 3.6em; line-height: 0.8; padding: 0.1em 0.12em 0 0; font-weight: 700;
    font-family: var(--header-font-family, inherit); color: var(--brand-primary-colour, inherit); }
.cms-brochure__band--drop-cap .cms-brochure__body > p + p { clear: left; }

/* ---- Buttons: read the portal's button settings (Residual 5, 8) ---------- */

.cms-hero__button, .cms-kind__button {
    display: inline-flex; align-items: center; padding: var(--content-button-padding, 0.625rem 1.125rem);
    border-radius: var(--content-button-radius, var(--buttons-border-radius, var(--radius-control, 0.5rem)));
    text-transform: var(--buttons-text-transform, none);
    font-size: var(--content-button-size, inherit);
    font-weight: var(--content-button-weight, 600);
    letter-spacing: var(--content-button-letter-spacing, normal);
    text-decoration: none;
    /* The edge is its own setting now (DEV-167); blank follows the ground,
       which is the edge every block button has always drawn. */
    border: var(--content-button-border-width, 1px) solid var(--content-button-primary-border-colour, var(--button-primary-bg, var(--brand-primary-colour, #691EDA)));
    box-shadow: var(--content-button-shadow-value, var(--content-button-shadow-custom, none));
}
.cms-hero__button--primary, .cms-kind__button--primary, .cms-band__button {
    background: var(--button-primary-bg, var(--brand-primary-colour, #691EDA)); color: var(--button-primary-fg, var(--text-primary-colour, #fff)); }
.cms-hero__button--primary:hover, .cms-kind__button--primary:hover, .cms-band__button:hover {
    background: var(--button-primary-hover-bg, var(--button-primary-bg, var(--brand-primary-colour, #691EDA)));
    color: var(--button-primary-hover-fg, var(--button-primary-fg, var(--text-primary-colour, #fff)));
    border-color: var(--button-primary-hover-border, var(--button-primary-bg, var(--brand-primary-colour, #691EDA)));
    box-shadow: var(--buttons-hover-shadow, var(--content-button-shadow-value, var(--content-button-shadow-custom, none))); }
.cms-hero__button--secondary { color: var(--button-secondary-fg, var(--brand-primary-colour, #691EDA)); background: var(--button-secondary-bg, transparent);
    border-color: var(--content-button-secondary-border-colour, var(--button-secondary-bg, var(--brand-primary-colour, #691EDA))); }
.cms-hero--dark .cms-hero__button--secondary, .cms-kind--tone-ink .cms-hero__button--secondary { color: inherit; border-color: var(--content-hero-dark-button-border-colour, var(--content-button-secondary-border-colour, rgba(255, 255, 255, 0.5))); background: transparent; }
/* The second button's shadow (step 29b): blank follows the first's. */
.cms-hero__button--secondary, .cms-band__button--ghost {
    box-shadow: var(--content-button-secondary-shadow, var(--content-button-shadow-value, var(--content-button-shadow-custom, none))); }
.cms-content-button-shadow-glow { --content-button-shadow-value: 0 10px 30px color-mix(in srgb, var(--button-primary-bg, var(--brand-primary-colour, #691EDA)) 40%, transparent); }
.cms-content-button-shadow-none { --content-button-shadow-value: none; }
/* The FIRST button of a hero or band, by content-button-primary-style
   (DEV-167) — the mirror of the second button's rules below. `solid` is the
   default drawing, named so a presence can say it out loud. */
.cms-content-button-primary-style-outline :is(.cms-hero__button--primary, .cms-kind__button--primary, .cms-band__button) {
    background: transparent; color: var(--content-button-primary-border-colour, var(--button-primary-bg, var(--brand-primary-colour, #691EDA))); }
.cms-content-button-primary-style-ghost :is(.cms-hero__button--primary, .cms-kind__button--primary, .cms-band__button) {
    background: transparent; border-color: transparent; color: inherit; }
.cms-content-button-primary-style-white :is(.cms-hero__button--primary, .cms-kind__button--primary, .cms-band__button) {
    background: #fff; color: var(--brand-ink, #1d1b22); border-color: var(--content-button-primary-border-colour, #fff); }
/* On a dark hero an outlined first button takes the hero's own edge colour,
   as the second one does, so the pair match. */
.cms-content-button-primary-style-outline .cms-hero--dark .cms-hero__button--primary,
.cms-content-button-primary-style-outline .cms-kind--tone-ink .cms-kind__button--primary {
    border-color: var(--content-hero-dark-button-border-colour, var(--content-button-primary-border-colour, currentColor)); }

/* A glyph in every block button (DEV-167). Generated content rather than an
   icon element: no markup change, and it follows the label's colour. */
.cms-content-button-icon-arrow :is(.cms-hero__button, .cms-kind__button, .cms-band__button)::after { content: "\2192"; }
.cms-content-button-icon-chevron :is(.cms-hero__button, .cms-kind__button, .cms-band__button)::after { content: "\203A"; }
.cms-content-button-icon-plus :is(.cms-hero__button, .cms-kind__button, .cms-band__button)::after { content: "\002B"; }
.cms-content-button-icon-external :is(.cms-hero__button, .cms-kind__button, .cms-band__button)::after { content: "\2197"; }
:is(.cms-content-button-icon-arrow, .cms-content-button-icon-chevron, .cms-content-button-icon-plus, .cms-content-button-icon-external)
    :is(.cms-hero__button, .cms-kind__button, .cms-band__button)::after {
    margin-left: var(--content-button-icon-space, 0.75rem); font-weight: 400; line-height: 1; }
/* Before the label instead: the same glyph, moved and mirrored in the box. */
:is(.cms-content-button-icon-arrow, .cms-content-button-icon-chevron, .cms-content-button-icon-plus, .cms-content-button-icon-external).cms-content-button-icon-side-before
    :is(.cms-hero__button, .cms-kind__button, .cms-band__button) { flex-direction: row-reverse; }
:is(.cms-content-button-icon-arrow, .cms-content-button-icon-chevron, .cms-content-button-icon-plus, .cms-content-button-icon-external).cms-content-button-icon-side-before
    :is(.cms-hero__button, .cms-kind__button, .cms-band__button)::after { margin-left: 0; margin-right: var(--content-button-icon-space, 0.75rem); }

/* The second button of a hero or band, by content-button-secondary-style. */
.cms-content-button-secondary-style-white .cms-hero__button--secondary,
.cms-content-button-secondary-style-white .cms-band__button--ghost { background: #fff; color: var(--brand-ink, #1d1b22); border-color: var(--content-button-secondary-border-colour, #fff); }
.cms-content-button-secondary-style-ghost .cms-hero__button--secondary,
.cms-content-button-secondary-style-ghost .cms-band__button--ghost { background: transparent; border-color: transparent; color: inherit; }
.cms-content-button-secondary-style-underline .cms-hero__button--secondary,
.cms-content-button-secondary-style-underline .cms-band__button--ghost { background: transparent; border: 0; border-radius: 0; padding-inline: 0;
    color: inherit; text-decoration: underline; text-underline-offset: 0.3em; }
.cms-content-button-secondary-style-outline .cms-hero__button--secondary,
.cms-content-button-secondary-style-outline .cms-band__button--ghost { background: transparent; border-color: var(--content-button-secondary-border-colour, currentColor); color: inherit; }
/* On a dark hero the second button sits on the hero's own ground, so its edge
   has its own colour; outline or not, the shared edge colour is the fallback. */
.cms-content-button-secondary-style-outline .cms-hero--dark .cms-hero__button--secondary {
    border-color: var(--content-hero-dark-button-border-colour, var(--content-button-secondary-border-colour, currentColor)); }

/* ---- Hero ---------------------------------------------------------------- */

.cms-hero { display: grid; gap: var(--content-hero-gap, 2rem); align-items: center; min-height: var(--content-hero-min-height, auto);
    padding: var(--content-hero-padding, 2.5rem 2.25rem); border-radius: var(--radius-panel, 1rem);
    background: color-mix(in srgb, var(--brand-primary-colour, #691EDA) 6%, var(--content-bg-colour, #fff)); }
.cms-hero--with-image { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
/* The dark ground and its text are settings (step 29b): --brand-ink is
   derived from the primary colour, so a brand whose primary is a warm accent
   got a brown hero it could not change. */
.cms-hero--dark { background: var(--content-hero-dark-bg, var(--brand-ink, #1d1b22)); color: var(--content-hero-dark-text, #fff); }
.cms-hero__title { margin: 0; font-size: var(--content-hero-title-size, clamp(1.75rem, 3vw, 2.5rem)); line-height: var(--content-hero-title-line-height, 1.15);
    letter-spacing: var(--content-hero-title-letter-spacing, normal); font-weight: var(--content-hero-title-weight, 700);
    text-transform: var(--content-hero-title-transform, none); max-width: var(--content-hero-title-measure, none); }
.cms-content-hero-title-transform-small-caps .cms-hero__title { text-transform: none; font-variant: small-caps; }
.cms-content-hero-title-font-heading .cms-hero__title { font-family: var(--header-font-family, inherit); }
.cms-content-hero-title-font-body .cms-hero__title { font-family: var(--font-family, inherit); }
.cms-hero__title em { display: block; font-style: normal; color: var(--content-hero-highlight-colour, var(--brand-primary-colour, #691EDA)); }
.cms-hero--dark .cms-hero__title em { color: var(--content-hero-dark-highlight-colour, var(--content-hero-highlight-colour, var(--brand-primary-soft, #c9adf7))); }
.cms-content-hero-highlight-style-italic .cms-hero__title em { font-style: italic; }
/* The standfirst is the hero's text at 90% unless it has a colour of its own,
   drawn at full strength (step 29b: a fixed opacity dimmed any colour). */
.cms-hero__standfirst { margin-top: var(--content-hero-standfirst-space, 1rem); font-size: var(--content-hero-standfirst-size, 1.0625rem);
    max-width: var(--content-hero-standfirst-measure, none); color: var(--content-hero-standfirst-colour, color-mix(in srgb, currentColor 90%, transparent)); }
/* A rule down the standfirst's left edge (content-hero-standfirst-decoration). */
.cms-content-hero-standfirst-decoration-left-rule .cms-hero__standfirst { padding-left: 1.25rem;
    border-left: var(--content-hero-standfirst-decoration-width, 4px) solid var(--content-hero-standfirst-decoration-colour, var(--brand-primary-colour, #691EDA)); }
.cms-hero__buttons { display: flex; flex-wrap: wrap; gap: var(--content-hero-buttons-gap, 0.75rem); margin-top: var(--content-hero-buttons-space, 1.5rem); }
.cms-hero__image { width: 100%; height: auto; border-radius: var(--radius-panel, 0.75rem); }
.cms-hero--dark .cms-kind__eyebrow { color: var(--brand-primary-soft, #c9adf7); }
/* Centred copy fills its track rather than shrinking to its words (step 29b):
   `justify-items: center` sized the copy to its longest line, so the title
   and standfirst measures could not take effect. */
.cms-hero--centre { text-align: center; justify-items: stretch; }
.cms-hero--centre .cms-hero__title { margin-inline: auto; }
.cms-hero--centre .cms-hero__buttons { justify-content: center; }
/* Joined buttons: no gap and no edge between them (content-hero-buttons-style). */
.cms-content-hero-buttons-style-joined .cms-hero__buttons { gap: 0; }
.cms-content-hero-buttons-style-joined .cms-hero__button + .cms-hero__button { border-left-width: 0; }
/* No panel behind a light hero (content-hero-surface): the words sit on the page. */
.cms-hero.cms-content-hero-surface-none:not(.cms-hero--dark, .cms-hero--plate) { background-color: transparent; border-radius: 0; }
.cms-hero--centre .cms-hero__standfirst { margin-inline: auto; max-width: var(--content-hero-standfirst-measure, 44rem); }
/* A background image sits under a scrim of the hero's own ground, its strength content-hero-scrim (78 light / 62 dark). */
.cms-hero--with-background { min-height: var(--content-hero-min-height, 22rem); background-size: cover; background-position: center;
    background-image: linear-gradient(color-mix(in srgb, var(--content-bg-colour, #fff) calc(var(--content-hero-scrim, 78) * 1%), transparent), color-mix(in srgb, var(--content-bg-colour, #fff) calc(var(--content-hero-scrim, 78) * 1%), transparent)), var(--cms-hero-background); }
.cms-hero--dark.cms-hero--with-background {
    background-image: linear-gradient(color-mix(in srgb, var(--content-hero-dark-bg, var(--brand-ink, #1d1b22)) calc(var(--content-hero-scrim, 62) * 1%), transparent), color-mix(in srgb, var(--content-hero-dark-bg, var(--brand-ink, #1d1b22)) calc(var(--content-hero-scrim, 62) * 1%), transparent)), var(--cms-hero-background); }
/* Size (Residual 14): display, large, compact; default is the fluid size above. */
.cms-hero--size-display .cms-hero__title { font-size: var(--content-hero-title-size, clamp(3rem, 8vw, 6rem)); line-height: var(--content-hero-title-line-height, 0.95); }
.cms-hero--size-large .cms-hero__title { font-size: var(--content-hero-title-size, clamp(2.25rem, 5vw, 4rem)); line-height: var(--content-hero-title-line-height, 1.05); }
.cms-hero--size-display, .cms-hero--size-large { padding: var(--content-hero-padding, clamp(3rem, 8vw, 6rem) 2.25rem); }
.cms-hero--size-compact { padding: var(--content-hero-padding, 1.5rem 1.75rem); }
.cms-hero--size-compact .cms-hero__title { font-size: var(--content-hero-title-size, clamp(1.375rem, 2.5vw, 1.875rem)); }
/* Image position: beside (the grid above), below the copy, or as the background. */
.cms-hero--image-below { grid-template-columns: minmax(0, 1fr); }
.cms-hero--image-below .cms-hero__image { order: 2; }
/* Image shape: plain, rounded (default), blob, window. */
.cms-hero--image-plain .cms-hero__image { border-radius: 0; }
.cms-hero--image-blob .cms-hero__image { border-radius: 58% 42% 55% 45% / 45% 55% 45% 55%; aspect-ratio: 1; object-fit: cover; }
.cms-hero--image-window .cms-hero__image { border: 1px solid var(--content-border-colour, #e5e7eb); border-radius: var(--radius-panel, 0.75rem);
    padding: 0.5rem; background: var(--content-bg-colour, #fff); box-shadow: 0 24px 48px rgba(10, 10, 10, 0.18); }
/* Highlight style: gradient paints the highlighted words with the brand pair. */
.cms-hero--highlight-gradient .cms-hero__title em, .cms-content-hero-highlight-style-gradient .cms-hero__title em {
    background-image: linear-gradient(90deg, var(--content-hero-highlight-colour, var(--brand-primary-colour, #691EDA)), var(--brand-secondary-colour, #691EDA));
    -webkit-background-clip: text; background-clip: text; color: transparent; }
/* The plate variant: a sub-page title plate — compact, eyebrow-sized headline over the highlighted line.
   It reads its own content-hero-plate-* settings first (step 29b), so a site's
   home hero and its sub-page plates can differ; blank falls back to the hero's
   own, which is what the plate drew before. Its ground is the dark hero's. */
.cms-hero--plate { padding: var(--content-hero-plate-padding, var(--content-hero-padding, 2rem 2.25rem 1.75rem)); border-radius: var(--radius-panel, 1rem);
    min-height: var(--content-hero-plate-min-height, var(--content-hero-min-height, auto));
    background: var(--content-hero-dark-bg, var(--brand-ink, #1d1b22)); color: var(--content-hero-dark-text, #fff); }
.cms-hero--plate .cms-hero__title { font-size: 0.85rem; letter-spacing: 0.3em; text-transform: uppercase; line-height: 1.2; font-weight: var(--content-hero-plate-label-weight, 700); }
.cms-hero--plate .cms-hero__title em { margin-top: var(--content-hero-plate-title-space, 0.75rem); font-size: var(--content-hero-plate-title-size, var(--content-hero-title-size, clamp(2rem, 5vw, 3.5rem)));
    letter-spacing: var(--content-hero-plate-title-letter-spacing, var(--content-hero-title-letter-spacing, -0.02em));
    line-height: var(--content-hero-plate-title-line-height, var(--content-hero-title-line-height, 1)); font-weight: var(--content-hero-plate-title-weight, inherit);
    text-transform: var(--content-hero-plate-title-transform, none); color: inherit; }
.cms-hero--plate :is(h1, h2), .cms-hero--plate .cms-kind__eyebrow { color: inherit; }
@media (max-width: 800px) { .cms-hero--with-image { grid-template-columns: minmax(0, 1fr); } }

/* ---- Callout ------------------------------------------------------------- */

.cms-callout { border-left: var(--content-callout-edge-width, 4px) solid var(--cms-callout-accent);
    border-radius: 0 var(--content-callout-radius, var(--radius-panel, 0.75rem)) var(--content-callout-radius, var(--radius-panel, 0.75rem)) 0;
    padding: var(--content-callout-padding, 1rem 1.25rem);
    background: var(--content-callout-bg, color-mix(in srgb, var(--cms-callout-accent) 8%, transparent)); }
.cms-callout--info { --cms-callout-accent: var(--content-callout-info-colour, var(--brand-primary-colour, #2563eb)); }
.cms-callout--success { --cms-callout-accent: var(--content-callout-success-colour, #16a34a); }
.cms-callout--warning { --cms-callout-accent: var(--content-callout-warning-colour, #d97706); }
/* A ground per tone (step 29b); blank follows the one callout ground. */
.cms-callout.cms-callout--info { background: var(--content-callout-info-bg, var(--content-callout-bg, color-mix(in srgb, var(--cms-callout-accent) 8%, transparent))); }
.cms-callout.cms-callout--success { background: var(--content-callout-success-bg, var(--content-callout-bg, color-mix(in srgb, var(--cms-callout-accent) 8%, transparent))); }
.cms-callout.cms-callout--warning { background: var(--content-callout-warning-bg, var(--content-callout-bg, color-mix(in srgb, var(--cms-callout-accent) 8%, transparent))); }
.cms-callout__title { margin: 0 0 0.375rem; font-weight: var(--content-callout-title-weight, 600); font-size: var(--content-callout-title-size, inherit);
    text-transform: var(--content-callout-title-transform, none); letter-spacing: var(--content-callout-title-letter-spacing, normal); }
.cms-content-callout-title-transform-small-caps .cms-callout__title { text-transform: none; font-variant: small-caps; }
.cms-content-callout-title-font-heading .cms-callout__title { font-family: var(--header-font-family, inherit); }
.cms-content-callout-title-font-body .cms-callout__title { font-family: var(--font-family, inherit); }
.cms-content-callout-layout-inline.cms-callout { display: grid; grid-template-columns: minmax(8rem, 1fr) minmax(0, 3fr); column-gap: 1.5rem; align-items: start; }
.cms-content-callout-layout-inline .cms-callout__title { margin: 0; }
.cms-content-callout-frame-outline.cms-callout { border: var(--content-callout-frame-width, 1px) solid var(--cms-callout-accent);
    border-left-width: var(--content-callout-edge-width, var(--content-callout-frame-width, 1px));
    border-radius: var(--content-callout-radius, var(--radius-panel, 0.75rem)); }
.cms-content-callout-frame-striped.cms-callout { border-left: 0; border-top: 14px solid transparent; border-radius: 0;
    border-image: repeating-linear-gradient(45deg, var(--brand-ink, #1d1b22) 0 14px, var(--cms-callout-accent) 14px 28px) 14; border-image-width: 14px 0 0 0; }

/* ---- Cards --------------------------------------------------------------- */

.cms-cards__lede { margin: var(--content-cards-lede-space, 0.5rem 0 0); max-width: var(--content-cards-lede-measure, 48rem); font-size: var(--content-cards-lede-size, inherit);
    color: var(--content-cards-lede-colour, inherit); }
.cms-content-cards-lede-align-centre .cms-cards__lede { margin-inline: auto; text-align: center; }
/* The column gap is its own setting (step 29b); blank follows the cards gap. */
.cms-cards__grid { display: grid; gap: var(--content-cards-gap, 1rem); column-gap: var(--content-cards-column-gap, var(--content-cards-gap, 1rem)); margin-top: 1.25rem;
    grid-template-columns: var(--cms-cards-columns, repeat(auto-fill, minmax(15rem, 1fr))); }
/* Card columns (Residual 36's neighbour): the choice sets the track list every
   card layout reads, so it holds whichever variant is drawing. */
.cms-content-cards-columns-auto { --cms-cards-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.cms-content-cards-columns-2 { --cms-cards-columns: repeat(2, minmax(0, 1fr)); }
.cms-content-cards-columns-3 { --cms-cards-columns: repeat(3, minmax(0, 1fr)); }
.cms-content-cards-columns-4 { --cms-cards-columns: repeat(4, minmax(0, 1fr)); }
.cms-card .cms-kind__prose { font-size: var(--content-card-body-size, inherit); }
.cms-card { display: flex; flex-direction: column; gap: var(--content-card-gap, 0.5rem); padding: var(--content-card-padding, 1.25rem);
    border-radius: var(--content-card-radius, var(--radius-panel, 0.75rem));
    border: var(--content-card-border-width, 1px) solid var(--cms-card-rule, var(--content-card-border-colour, var(--content-border-colour, #e5e7eb)));
    background: var(--cms-card-tint, var(--content-card-bg, var(--content-bg-colour, #fff)));
    box-shadow: var(--content-card-shadow-value, none); }
/* ---- A card's own picture (DEV-167) -------------------------------------
   The picture leads the card: full width, cropped to a fixed height, or to a
   ratio when one is chosen. `behind` makes it the card's ground instead, with
   the words over a scrim. The card's flex gap already spaces the rows, so the
   space setting is the picture's own margin over it. */
.cms-card__image { display: block; width: 100%; height: var(--content-card-image-height, 210px); object-fit: cover;
    border-radius: var(--content-card-image-radius, var(--content-card-radius, var(--radius-panel, 0.75rem)));
    margin-bottom: var(--content-card-image-space, 0); }
.cms-content-card-image-ratio-16-9 .cms-card__image { height: auto; aspect-ratio: 16 / 9; }
.cms-content-card-image-ratio-3-2 .cms-card__image { height: auto; aspect-ratio: 3 / 2; }
.cms-content-card-image-ratio-4-3 .cms-card__image { height: auto; aspect-ratio: 4 / 3; }
.cms-content-card-image-ratio-1-1 .cms-card__image { height: auto; aspect-ratio: 1 / 1; }
.cms-content-card-image-ratio-auto .cms-card__image { height: auto; aspect-ratio: auto; object-fit: contain; }
/* Behind the words: the picture fills the card and the copy sits over it on a
   scrim, so text on a photograph stays readable whatever the photograph is. */
.cms-content-card-image-position-behind .cms-card { position: relative; isolation: isolate; overflow: hidden; color: #fff; }
.cms-content-card-image-position-behind .cms-card__image { position: absolute; inset: 0; width: 100%; height: 100%;
    margin: 0; border-radius: inherit; z-index: -2; }
.cms-content-card-image-position-behind .cms-card::before { content: ""; position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.7)); border-radius: inherit; }
.cms-content-card-image-position-behind .cms-card :is(h3, p, .cms-card__link, .cms-kind__prose a) { color: inherit; }
.cms-card__icon { width: var(--content-card-icon-size, 1.75rem); height: var(--content-card-icon-size, 1.75rem); color: var(--content-card-icon-colour, var(--brand-primary-colour, #691EDA)); }
.cms-card__title { margin: var(--content-card-title-space, 0); font-weight: var(--content-card-title-weight, 600); font-size: var(--content-card-title-size, 1.0625rem);
    line-height: var(--content-card-title-line-height, inherit); text-transform: var(--content-card-title-transform, none);
    letter-spacing: var(--content-card-title-letter-spacing, var(--header-letter-spacing, normal)); }
.cms-content-card-title-transform-small-caps .cms-card__title { text-transform: none; font-variant: small-caps; }
.cms-content-card-title-font-heading .cms-card__title { font-family: var(--header-font-family, inherit); }
.cms-content-card-title-font-body .cms-card__title { font-family: var(--font-family, inherit); }
.cms-card__link { margin-top: auto; font-weight: var(--content-card-link-weight, 600); font-size: var(--content-card-link-size, inherit);
    text-transform: var(--content-card-link-transform, none); letter-spacing: var(--content-card-link-letter-spacing, normal);
    color: var(--content-card-link-colour, var(--content-card-icon-colour, var(--brand-primary-colour, #691EDA))); text-decoration: none; }
.cms-content-card-link-transform-small-caps .cms-card__link { text-transform: none; font-variant: small-caps; }
/* Whole-card link: the link's hit area is stretched over the card. */
.cms-card--linked { position: relative; transition: border-color 0.15s, transform 0.15s, background-color 0.15s, color 0.15s; }
.cms-card--linked:hover { border-color: var(--brand-primary-colour, #691EDA); transform: translateY(-2px); }
.cms-card--linked .cms-card__link::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.cms-card--linked .cms-kind__prose a { position: relative; z-index: 1; }
/* The cycling tints (content-card-tint-1/2/3) and a card's own tone or accent. */
/* The cycle runs to six (Residual 36): tints 4-6 fall back to 1-3, so three
   tints still repeat every three cards and blank still draws one ground. */
.cms-card:nth-child(6n + 1) { --cms-card-tint: var(--content-card-tint-1, var(--content-card-bg, var(--content-bg-colour, #fff))); }
.cms-card:nth-child(6n + 2) { --cms-card-tint: var(--content-card-tint-2, var(--content-card-bg, var(--content-bg-colour, #fff))); }
.cms-card:nth-child(6n + 3) { --cms-card-tint: var(--content-card-tint-3, var(--content-card-bg, var(--content-bg-colour, #fff))); }
.cms-card:nth-child(6n + 4) { --cms-card-tint: var(--content-card-tint-4, var(--content-card-tint-1, var(--content-card-bg, var(--content-bg-colour, #fff)))); }
.cms-card:nth-child(6n + 5) { --cms-card-tint: var(--content-card-tint-5, var(--content-card-tint-2, var(--content-card-bg, var(--content-bg-colour, #fff)))); }
.cms-card:nth-child(6n) { --cms-card-tint: var(--content-card-tint-6, var(--content-card-tint-3, var(--content-card-bg, var(--content-bg-colour, #fff)))); }
.cms-card--tone-panel { --cms-card-tint: var(--content-tone-panel-bg, var(--content-bg-colour, #fff)); color: var(--content-tone-panel-text, inherit); }
.cms-card--tone-tint { --cms-card-tint: var(--content-tone-tint-bg, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 8%, var(--content-bg-colour, #fff)))); }
.cms-card--tone-ink { --cms-card-tint: var(--content-tone-ink-bg, var(--brand-ink, #1d1b22)); color: var(--content-tone-ink-text, #fff); border-color: transparent; }
.cms-card--tone-brand { --cms-card-tint: var(--content-tone-brand-bg, var(--brand-primary-colour, #691EDA)); color: var(--content-tone-brand-text, var(--text-primary-colour, #fff)); border-color: transparent; }
.cms-card--tone-ink :is(h3, .cms-card__icon, .cms-card__link, .cms-kind__prose a),
.cms-card--tone-brand :is(h3, .cms-card__icon, .cms-card__link, .cms-kind__prose a) { color: inherit; }
/* `none` is not a valid item in a shadow list, so pairing the accent with the
   blank shadow's fallback dropped the whole declaration — and the accent with
   it. The fallback here is a no-op shadow instead. */
.cms-card--accent { box-shadow: inset 0 var(--content-card-accent-width, 0.5rem) 0 var(--cms-card-accent), var(--content-card-shadow-value, 0 0 0 0 transparent); }
.cms-card--emphasis { transform: translateY(-0.5rem); box-shadow: 0 16px 40px rgba(10, 10, 10, 0.14); border-color: var(--brand-primary-colour, #691EDA); }
/* Shadow, hover, icon style, link style — by the cards group's selects. */
.cms-content-card-shadow-soft { --content-card-shadow-value: 0 2px 8px rgba(10, 10, 10, 0.08); }
.cms-content-card-shadow-raised { --content-card-shadow-value: 0 8px 24px rgba(10, 10, 10, 0.12); }
.cms-content-card-shadow-none { --content-card-shadow-value: none; }
.cms-content-card-hover-lift .cms-card { transition: transform 0.15s, box-shadow 0.15s; }
.cms-content-card-hover-lift .cms-card:hover { transform: translateY(-4px); box-shadow: 0 12px 32px rgba(10, 10, 10, 0.12); }
.cms-content-card-hover-invert .cms-card { transition: background-color 0.15s, color 0.15s; }
.cms-content-card-hover-invert .cms-card:hover { background: var(--content-tone-ink-bg, var(--brand-ink, #1d1b22)); color: var(--content-tone-ink-text, #fff); }
.cms-content-card-hover-invert .cms-card:hover :is(h3, .cms-card__icon, .cms-card__link, .cms-kind__prose a) { color: inherit; }
.cms-content-card-hover-none .cms-card, .cms-content-card-hover-none .cms-card--linked:hover { transform: none; box-shadow: var(--content-card-shadow-value, none); }
.cms-content-card-icon-style-disc .cms-card__icon, .cms-content-card-icon-style-square .cms-card__icon {
    width: var(--content-card-icon-size, 3rem); height: var(--content-card-icon-size, 3rem); padding: calc(var(--content-card-icon-size, 3rem) / 4);
    background: var(--content-card-icon-bg, var(--content-bg-colour, #fff)); box-shadow: 0 2px 8px rgba(10, 10, 10, 0.08); }
.cms-content-card-icon-style-disc .cms-card__icon { border-radius: 50%; }
.cms-content-card-icon-style-square .cms-card__icon { border-radius: var(--radius-control, 0.5rem); }
.cms-content-card-icon-style-hidden .cms-card__icon { display: none; }
/* Top-right: the icon pinned in the card's top corner, clear of the copy. It
   shows on the numbered variant too, which otherwise hides it. */
.cms-content-card-icon-style-top-right .cms-card { position: relative; }
.cms-content-card-icon-style-top-right .cms-card__icon { position: absolute; top: 1.25rem; right: 1.25rem; opacity: 0.6; }
.cms-cards.cms-kind--numbered.cms-content-card-icon-style-top-right .cms-card__icon { display: block; }
.cms-content-card-link-style-pill .cms-card__link { align-self: flex-start; padding: 0.5rem 1rem; border-radius: 9999px;
    background: var(--content-card-link-bg, var(--button-primary-bg, var(--brand-primary-colour, #691EDA))); color: var(--content-card-link-colour, var(--button-primary-fg, var(--text-primary-colour, #fff))); }
/* Boxed: the link drawn in a box of its own colour, filled with the primary button's on hover. */
.cms-content-card-link-style-boxed .cms-card__link { align-self: flex-start; justify-self: end; padding: 0.6rem 0.8rem; color: var(--content-card-link-colour, inherit);
    border: var(--content-card-link-border-width, 2px) solid currentColor; background: var(--content-card-link-bg, transparent); transition: background-color 0.15s, color 0.15s, border-color 0.15s; }
/* A register row is one line of columns, so its boxed link centres on the row
   like the rest of it; pinned to the top it sat off-centre whenever the copy
   wrapped. */
.cms-cards.cms-kind--register.cms-content-card-link-style-boxed .cms-card__link { align-self: center; }
.cms-content-card-link-style-boxed .cms-card:hover .cms-card__link { background: var(--button-primary-bg, var(--brand-primary-colour, #691EDA));
    border-color: var(--button-primary-bg, var(--brand-primary-colour, #691EDA)); color: var(--button-primary-fg, var(--text-primary-colour, #fff)); }
.cms-content-card-link-style-end-cap .cms-card { position: relative; padding-right: 3.5rem; }
.cms-content-card-link-style-end-cap .cms-card__link { position: absolute; right: 1.25rem; top: 50%; transform: translateY(-50%); font-size: 1.5rem; line-height: 1; }

/* Cards · list: full-width rows, icon | copy | link. */
.cms-cards.cms-kind--list .cms-cards__grid { grid-template-columns: minmax(0, 1fr); gap: 0; border-top: var(--content-card-border-width, 1px) solid var(--cms-card-rule, var(--content-card-border-colour, var(--content-border-colour, #e5e7eb))); }
.cms-cards.cms-kind--list .cms-card { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr) auto; column-gap: 1.25rem; align-items: start;
    padding: 1.25rem 0; border: 0; border-bottom: var(--content-card-border-width, 1px) solid var(--cms-card-rule, var(--content-card-border-colour, var(--content-border-colour, #e5e7eb))); border-radius: 0; background: transparent; }
.cms-cards.cms-kind--list .cms-card > * { grid-column: 2; }
.cms-cards.cms-kind--list .cms-card__icon { grid-column: 1; grid-row: 1 / span 3; }
.cms-cards.cms-kind--list .cms-card__link { grid-column: 3; grid-row: 1; margin-top: 0; white-space: nowrap; }

/* Cards · numbered: two ruled columns, each card counted (content-card-numbering; a numbering label prefixes the count). */
.cms-cards.cms-kind--numbered .cms-cards__grid, .cms-cards.cms-kind--register .cms-cards__grid { counter-reset: cms-card; }
.cms-cards.cms-kind--numbered .cms-cards__grid { grid-template-columns: var(--cms-cards-columns, repeat(2, minmax(0, 1fr))); row-gap: var(--content-cards-gap, 0); column-gap: var(--content-cards-column-gap, 3rem);
    border-top: var(--content-card-border-width, 1px) solid var(--cms-card-rule, var(--content-card-border-colour, var(--content-border-colour, #e5e7eb))); }
/* The numbered and register rows pad themselves (their numeral hangs in the
   padding), so each reads its own padding setting (step 29b) rather than
   the grid card's. */
.cms-cards.cms-kind--numbered .cms-card { counter-increment: cms-card; position: relative; padding: var(--content-card-numbered-padding, 1.25rem 0 1.25rem 3.25rem); border: 0;
    border-bottom: var(--content-card-border-width, 1px) solid var(--cms-card-rule, var(--content-card-border-colour, var(--content-border-colour, #e5e7eb))); border-radius: 0; background: transparent; }
.cms-cards.cms-kind--numbered .cms-card::before, .cms-cards.cms-kind--register .cms-card::before {
    content: var(--cms-card-numbering-label, '') counter(cms-card, decimal-leading-zero); position: absolute; left: 0; top: 1.2rem;
    font-size: var(--content-card-number-size, 1.375rem); font-weight: var(--content-card-number-weight, 700);
    letter-spacing: var(--content-card-number-letter-spacing, normal); line-height: 1.2;
    color: var(--content-card-number-colour, var(--brand-primary-colour, #691EDA)); }
/* The variant rules above are 0-3-0, so these have to match that weight — and
   the choice class sits on the same element as the variant (rootClasses()),
   so it compounds with it rather than containing it. */
.cms-cards.cms-kind--numbered.cms-content-card-numbering-decimal .cms-card::before,
.cms-cards.cms-kind--register.cms-content-card-numbering-decimal .cms-card::before { content: var(--cms-card-numbering-label, '') counter(cms-card, decimal); }
.cms-cards.cms-kind--numbered.cms-content-card-numbering-roman .cms-card::before,
.cms-cards.cms-kind--register.cms-content-card-numbering-roman .cms-card::before { content: var(--cms-card-numbering-label, '') counter(cms-card, upper-roman); }
.cms-cards.cms-kind--numbered .cms-card__icon { display: none; }

/* Cards · register: ruled rows — number | icon | title | copy | end-cap link — that invert on hover (Residual 16). */
.cms-cards.cms-kind--register .cms-cards__grid { display: block; margin-top: 1.25rem;
    border-top: 2px solid var(--cms-card-rule, var(--content-card-border-colour, var(--brand-ink, #1d1b22))); }
.cms-cards.cms-kind--register .cms-card { counter-increment: cms-card; position: relative; display: grid; grid-template-columns: 5rem 2.5rem minmax(10rem, 1fr) 2fr auto; align-items: center;
    gap: var(--content-card-register-gap, var(--content-cards-column-gap, 1.5rem)); padding: var(--content-card-register-padding, 1.5rem 0.5rem 1.5rem 0); border: 0; border-bottom: 2px solid var(--cms-card-rule, var(--content-card-border-colour, var(--brand-ink, #1d1b22))); border-radius: 0; background: transparent;
    transition: background-color 0.15s, color 0.15s; }
.cms-cards.cms-kind--register .cms-card::before { position: static; grid-column: 1; font-size: var(--content-card-number-size, 2.5rem); line-height: 1; }
.cms-cards.cms-kind--register .cms-card__icon { grid-column: 2; }
.cms-cards.cms-kind--register .cms-card__title { grid-column: 3; }
.cms-cards.cms-kind--register .cms-card .cms-kind__prose { grid-column: 4; }
.cms-cards.cms-kind--register .cms-card__link { grid-column: 5; margin: 0; white-space: nowrap; }
.cms-cards.cms-kind--register .cms-card:hover { background: var(--content-tone-ink-bg, var(--brand-ink, #1d1b22)); color: var(--content-tone-ink-text, #fff); }
.cms-cards.cms-kind--register .cms-card:hover :is(h3, .cms-card__icon, .cms-card__link, .cms-kind__prose a, ::before) { color: inherit; }

/* Cards on a dark ground (step 29b): a rule drawn in the content border
   colour vanishes on ink, so a card on a dark ground takes its rule from
   content-card-ink-border-colour. Unset, the property below is invalid and
   every rule falls back to the colour it drew before. */
.cms-cards:is(.cms-kind--tone-ink, .cms-kind--tone-brand), :is(.cms-brochure__band--tone-ink, .cms-brochure__band--tone-brand) > .cms-cards,
.cms-card:is(.cms-card--tone-ink, .cms-card--tone-brand) { --cms-card-rule: var(--content-card-ink-border-colour); }

/* Cards · bento: a four-column board; the first card leads, the fourth is wide. */
.cms-cards.cms-kind--bento .cms-cards__grid { grid-template-columns: var(--cms-cards-columns, repeat(4, minmax(0, 1fr))); grid-auto-rows: minmax(10rem, auto); }
.cms-cards.cms-kind--bento .cms-card:nth-child(1) { grid-column: span 2; grid-row: span 2; padding: 2rem; border-color: transparent;
    background: var(--content-tone-brand-bg, var(--brand-primary-colour, #691EDA)); color: var(--content-tone-brand-text, var(--text-primary-colour, #fff)); }
.cms-cards.cms-kind--bento .cms-card:nth-child(1) .cms-card__title { font-size: 1.625rem; }
.cms-cards.cms-kind--bento .cms-card:nth-child(1) .cms-card__title,
.cms-cards.cms-kind--bento .cms-card:nth-child(1) .cms-card__icon,
.cms-cards.cms-kind--bento .cms-card:nth-child(1) .cms-card__link,
.cms-cards.cms-kind--bento .cms-card:nth-child(1) .cms-kind__prose a { color: inherit; }
.cms-cards.cms-kind--bento .cms-card:nth-child(4) { grid-column: span 2; }
.cms-cards.cms-kind--bento .cms-card:nth-child(5):last-child { grid-column: 1 / -1; }
@media (max-width: 800px) {
    .cms-cards.cms-kind--numbered .cms-cards__grid { grid-template-columns: minmax(0, 1fr); }
    .cms-cards.cms-kind--bento .cms-cards__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .cms-cards.cms-kind--list .cms-card { grid-template-columns: 2.5rem minmax(0, 1fr); }
    .cms-cards.cms-kind--list .cms-card__link { grid-column: 2; grid-row: auto; }
    .cms-cards.cms-kind--register .cms-card { grid-template-columns: 4rem minmax(0, 1fr); }
    .cms-cards.cms-kind--register .cms-card > * { grid-column: 2; }
    .cms-cards.cms-kind--register .cms-card::before { grid-column: 1; grid-row: 1 / span 4; }
}

/* ---- FAQ ----------------------------------------------------------------- */

.cms-faq__list { margin-top: 1rem; border-top: var(--content-faq-rule-width, 1px) solid var(--content-faq-rule-colour, var(--content-border-colour, #e5e7eb)); }
.cms-faq__item { border-bottom: var(--content-faq-rule-width, 1px) solid var(--content-faq-rule-colour, var(--content-border-colour, #e5e7eb)); }
.cms-faq__question { cursor: pointer; list-style: none; padding: var(--content-faq-question-padding, 1rem 0);
    font-weight: var(--content-faq-question-weight, 600); font-size: var(--content-faq-question-size, inherit);
    letter-spacing: var(--content-faq-question-letter-spacing, normal); display: flex; justify-content: space-between; gap: 1rem;
    text-transform: var(--content-faq-question-transform, none); }
.cms-faq__question::-webkit-details-marker { display: none; }
.cms-faq__question::after { content: '+'; font-size: var(--content-faq-marker-size, inherit); color: var(--content-faq-marker-colour, var(--brand-primary-colour, #691EDA)); }
.cms-faq__item[open] .cms-faq__question::after { content: '\2212'; }
.cms-faq__answer { padding: var(--content-faq-answer-padding, 0 0 1rem); font-size: var(--content-faq-answer-size, inherit); max-width: var(--content-faq-answer-measure, none); }
.cms-content-faq-question-transform-uppercase .cms-faq__question { text-transform: uppercase;
    letter-spacing: var(--content-faq-question-letter-spacing, 0.06em); font-size: var(--content-faq-question-size, 0.9375rem); }
.cms-content-faq-question-transform-small-caps .cms-faq__question { font-variant: small-caps; }
.cms-content-faq-question-font-heading .cms-faq__question { font-family: var(--header-font-family, inherit); }
.cms-content-faq-rows-cards .cms-faq__list { border-top: 0; display: grid; gap: var(--content-faq-gap, 0.75rem); }
.cms-content-faq-rows-cards .cms-faq__item { border: 0; border-radius: var(--radius-panel, 0.75rem); padding: 0 1.25rem;
    background: var(--content-card-bg, var(--content-bg-colour, #fff)); box-shadow: 0 2px 8px rgba(10, 10, 10, 0.08); }

/* ---- Stats --------------------------------------------------------------- */

/* Stats · band (default): one ruled row, a divider between numbers. */
.cms-stats__grid { display: grid; grid-template-columns: var(--cms-stat-columns, repeat(auto-fit, minmax(10rem, 1fr))); gap: var(--content-stats-gap, 0);
    margin: var(--content-stats-grid-space, 1.25rem 0 0);
    border-top: var(--content-stat-rule-value, var(--content-stat-rule-width, 1px) solid var(--content-stat-rule-colour, var(--content-border-colour, #e5e7eb)));
    border-bottom: var(--content-stat-rule-value, var(--content-stat-rule-width, 1px) solid var(--content-stat-rule-colour, var(--content-border-colour, #e5e7eb))); }
.cms-stat { padding: var(--content-stat-padding, 1.5rem 1.25rem); text-align: center; border-left: var(--content-stat-rule-value, var(--content-stat-rule-width, 1px) solid var(--content-stat-rule-colour, var(--content-border-colour, #e5e7eb))); }
.cms-content-stat-align-start .cms-stat { text-align: left; }
.cms-content-stat-align-centre .cms-stat { text-align: center; }
.cms-content-stat-align-end .cms-stat { text-align: right; }
.cms-stat:first-child { border-left: 0; }
.cms-stat__value { font-size: var(--content-stat-value-size, clamp(1.75rem, 3.2vw, 2.5rem)); font-weight: var(--content-stat-value-weight, 700);
    line-height: var(--content-stat-value-line-height, 1.1); letter-spacing: var(--content-stat-value-letter-spacing, normal);
    color: var(--content-stat-value-colour, var(--brand-primary-colour, #691EDA)); }
.cms-stat__label { margin: var(--content-stat-label-space, 0.5rem) 0 0; font-size: var(--content-stat-label-size, 0.9375rem);
    font-weight: var(--content-stat-label-weight, inherit); color: var(--content-stat-label-colour, color-mix(in srgb, currentColor 80%, transparent)); }
.cms-content-stat-value-font-heading .cms-stat__value { font-family: var(--header-font-family, inherit); }
.cms-content-stat-label-style-uppercase .cms-stat__label { text-transform: uppercase; letter-spacing: 0.12em;
    font-size: var(--content-stat-label-size, 0.75rem); font-weight: var(--content-stat-label-weight, 700); color: var(--content-stat-label-colour, inherit); }
.cms-content-stat-label-style-small-caps .cms-stat__label { font-variant: small-caps; letter-spacing: 0.06em; }
.cms-content-stat-rule-style-double { --content-stat-rule-value: calc(3 * var(--content-stat-rule-width, 1px)) double var(--content-stat-rule-colour, var(--content-border-colour, #e5e7eb)); }
.cms-content-stat-rule-style-none { --content-stat-rule-value: 0; }
.cms-content-stat-rule-style-hairline { --content-stat-rule-value: var(--content-stat-rule-width, 1px) solid var(--content-stat-rule-colour, var(--content-border-colour, #e5e7eb)); }
/* Dividers: the rules between the figures only, none above or below the row. */
.cms-content-stat-rule-style-dividers .cms-stats__grid { border-top: 0; border-bottom: 0; }
.cms-stats--columns-2 { --cms-stat-columns: repeat(2, minmax(0, 1fr)); }
.cms-stats--columns-3 { --cms-stat-columns: repeat(3, minmax(0, 1fr)); }
.cms-stats--columns-4 { --cms-stat-columns: repeat(4, minmax(0, 1fr)); }
.cms-kind--tone-ink .cms-stat__value, .cms-kind--tone-brand .cms-stat__value, .cms-kind--tone-image .cms-stat__value { color: var(--content-stat-value-colour, inherit); }
/* The figures' heading size (step 29b): a strip of figures often carries a
   smaller heading than the site's sections. It must outweigh the portal's
   own section-heading rule, which loads after this sheet, and blank repeats
   that rule's value. */
.cms-stats.cms-kind .cms-system-section__heading.ui-heading { font-size: var(--content-stats-heading-size, var(--section-heading-size, 1.125rem)); }
/* Stats · bubbles: each number in a soft round of a brand tint, alternately dropped. */
.cms-stats.cms-kind--bubbles .cms-stats__grid { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--content-stats-gap, 1.5rem); border: 0; padding-bottom: 1.5rem; }
.cms-stats.cms-kind--bubbles .cms-stat { display: flex; flex-direction: column; justify-content: center;
    width: var(--content-stat-bubble-size, 12rem); height: var(--content-stat-bubble-size, 12rem); padding: var(--content-stat-padding, 1.25rem);
    border: 0; border-radius: 50%; background: var(--content-stat-bubble-tint-1, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 14%, var(--content-bg-colour, #fff)))); }
.cms-stats.cms-kind--bubbles .cms-stat:nth-child(3n + 2) { transform: translateY(1.5rem);
    background: var(--content-stat-bubble-tint-2, var(--brand-secondary-soft, color-mix(in srgb, var(--brand-secondary-colour, #691EDA) 14%, var(--content-bg-colour, #fff)))); }
.cms-stats.cms-kind--bubbles .cms-stat:nth-child(3n) {
    background: var(--content-stat-bubble-tint-3, var(--brand-accent-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 7%, var(--content-bg-colour, #fff)))); }
.cms-stats.cms-kind--bubbles .cms-stat__value { font-size: var(--content-stat-value-size, 2.125rem); }

/* ---- Steps --------------------------------------------------------------- */

/* Steps · rail (default): columns hung from a brand rule, a marker at each step. */
.cms-steps__lede { margin: var(--content-steps-lede-space, 0.5rem 0 0); max-width: var(--content-steps-lede-measure, 48rem); font-size: var(--content-steps-lede-size, inherit);
    color: var(--content-steps-lede-colour, inherit); line-height: var(--content-steps-lede-line-height, var(--content-body-line-height, var(--content-line-height, 1.65))); }
.cms-content-steps-columns-auto { --cms-steps-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.cms-content-steps-columns-2 { --cms-steps-columns: repeat(2, minmax(0, 1fr)); }
.cms-content-steps-columns-3 { --cms-steps-columns: repeat(3, minmax(0, 1fr)); }
.cms-content-steps-columns-4 { --cms-steps-columns: repeat(4, minmax(0, 1fr)); }
.cms-content-steps-columns-5 { --cms-steps-columns: repeat(5, minmax(0, 1fr)); }
.cms-step .cms-kind__prose { font-size: var(--content-step-body-size, inherit); color: var(--content-step-body-colour, inherit);
    line-height: var(--content-step-body-line-height, var(--content-body-line-height, var(--content-line-height, 1.65))); }
.cms-steps__list { list-style: none; margin: var(--content-steps-list-space, 2rem 0 0); padding: 0; display: grid;
    gap: var(--content-steps-gap, normal); grid-template-columns: var(--cms-steps-columns, repeat(auto-fit, minmax(12rem, 1fr)));
    border-top: var(--content-step-path-value, var(--content-step-path-width, 3px) solid var(--content-step-path-colour, var(--brand-primary-colour, #691EDA))); }
.cms-step { position: relative; padding: var(--content-step-padding, 1.5rem 1.5rem 0 0); }
/* The marker sits centred on the path: half its size and half the path's
   width above the step (blank: 15px on a 3px path, 9px up). Its size and the
   ring that clears the path round it are settings (step 29b). */
.cms-step::before { content: ''; position: absolute; top: calc(var(--content-step-path-width, 3px) / -2 - var(--content-step-marker-size, 0.9375rem) / 2); left: 0;
    width: var(--content-step-marker-size, 0.9375rem); height: var(--content-step-marker-size, 0.9375rem); border-radius: var(--content-step-marker-radius, 50%);
    background: var(--content-step-marker-colour, var(--brand-primary-colour, #691EDA)); box-shadow: 0 0 0 4px var(--content-step-marker-ring-colour, var(--content-bg-colour, #fff)); }
.cms-step:nth-child(2n)::before { background: var(--content-step-marker-alt-colour, var(--content-step-marker-colour, var(--brand-primary-colour, #691EDA))); }
.cms-step__number { display: block; font-size: var(--content-step-number-size, 0.8125rem); font-weight: var(--content-step-number-weight, 700);
    letter-spacing: var(--content-step-number-letter-spacing, 0.16em); color: var(--content-step-number-colour, var(--brand-primary-colour, #691EDA)); }
.cms-step__title { margin: 0.25rem 0 var(--content-step-title-space, 0.375rem); font-size: var(--content-step-title-size, 1.125rem);
    font-weight: var(--content-step-title-weight, 600); text-transform: var(--content-step-title-transform, none);
    letter-spacing: var(--content-step-title-letter-spacing, var(--header-letter-spacing, normal)); }
/* The numeral on the step's first line rather than above it (content-step-number-position). */
.cms-content-step-number-position-inline .cms-step__number { display: inline; }
.cms-content-step-number-font-heading .cms-step__number { font-family: var(--header-font-family, inherit); }
.cms-content-step-number-font-body .cms-step__number { font-family: var(--font-family, inherit); }
.cms-content-step-title-transform-small-caps .cms-step__title { text-transform: none; font-variant: small-caps; }
.cms-content-step-title-font-heading .cms-step__title { font-family: var(--header-font-family, inherit); }
.cms-content-step-title-font-body .cms-step__title { font-family: var(--font-family, inherit); }
.cms-content-step-marker-square { --content-step-marker-radius: 0; }
.cms-content-step-marker-none .cms-step::before { content: none; }
.cms-content-step-marker-numbered-disc .cms-step::before { content: none; }
.cms-content-step-marker-numbered-disc .cms-step__number { display: grid; place-items: center;
    width: var(--content-step-marker-size, 2.25rem); height: var(--content-step-marker-size, 2.25rem);
    margin-top: calc(-1.5rem - var(--content-step-marker-size, 2.25rem) / 2); margin-bottom: 0.75rem;
    border-radius: 50%; letter-spacing: 0; font-size: var(--content-step-number-size, 0.875rem); background: var(--content-step-marker-colour, var(--brand-primary-colour, #691EDA)); color: var(--text-primary-colour, #fff);
    box-shadow: 0 0 0 4px var(--content-step-marker-ring-colour, var(--content-bg-colour, #fff)); }
/* The alternate marker colour reaches the numbered disc too (step 29b). */
.cms-content-step-marker-numbered-disc .cms-step:nth-child(2n) .cms-step__number {
    background: var(--content-step-marker-alt-colour, var(--content-step-marker-colour, var(--brand-primary-colour, #691EDA))); }
.cms-content-step-path-dotted { --content-step-path-value: var(--content-step-path-width, 3px) dotted var(--content-step-path-colour, var(--brand-primary-colour, #691EDA)); }
.cms-content-step-path-none { --content-step-path-value: 0; }
.cms-content-step-path-rule { --content-step-path-value: var(--content-step-path-width, 3px) solid var(--content-step-path-colour, var(--brand-primary-colour, #691EDA)); }
/* A tile reads the step padding and its own space, radius, ground and edge
   (step 29b): these were literals at a weight the step padding could not
   reach. */
.cms-content-step-tile-glass .cms-step, .cms-content-step-tile-panel .cms-step { margin-top: var(--content-step-tile-space, 1.25rem); padding: var(--content-step-padding, 1.25rem);
    border-radius: var(--content-step-tile-radius, var(--radius-panel, 0.75rem)); }
.cms-content-step-tile-glass .cms-step { background: var(--content-step-tile-bg, color-mix(in srgb, currentColor 8%, transparent));
    border: var(--content-step-tile-border-width, 1px) solid var(--content-step-tile-border-colour, color-mix(in srgb, currentColor 18%, transparent)); backdrop-filter: blur(8px); }
.cms-content-step-tile-panel .cms-step { background: var(--content-step-tile-bg, var(--content-card-bg, var(--content-bg-colour, #fff)));
    border: var(--content-step-tile-border-width, 1px) solid var(--content-step-tile-border-colour, var(--content-border-colour, #e5e7eb)); }
.cms-content-step-tile-none.cms-kind--vertical .cms-step { background: transparent; border: 0; padding-inline: 0; }
.cms-content-step-number-style-gradient .cms-step__number { font-size: var(--content-step-number-size, 1.75rem); letter-spacing: var(--content-step-number-letter-spacing, 0);
    background-image: linear-gradient(90deg, var(--content-step-number-colour, var(--brand-primary-colour, #691EDA)), var(--brand-secondary-colour, #691EDA));
    -webkit-background-clip: text; background-clip: text; color: transparent; }
.cms-content-step-number-style-italic .cms-step__number { font-style: italic; font-family: var(--header-font-family, inherit); font-size: var(--content-step-number-size, 1.5rem);
    letter-spacing: var(--content-step-number-letter-spacing, 0); font-weight: var(--content-step-number-weight, 400); }
.cms-content-step-stagger-on .cms-step:nth-child(2n), .cms-steps--stagger .cms-step:nth-child(2n) { padding-top: 3.5rem; }
.cms-content-step-stagger-on .cms-step:nth-child(2n)::before, .cms-steps--stagger .cms-step:nth-child(2n)::before {
    top: calc(2rem - var(--content-step-path-width, 3px) / 2 - var(--content-step-marker-size, 0.9375rem) / 2); }
.cms-steps--stagger-off .cms-step:nth-child(2n) { padding-top: 1.5rem; }
.cms-steps--stagger-off .cms-step:nth-child(2n)::before { top: calc(var(--content-step-path-width, 3px) / -2 - var(--content-step-marker-size, 0.9375rem) / 2); }
/* Steps · vertical: stacked panels, the number in a round beside the copy. */
.cms-steps.cms-kind--vertical .cms-steps__list { grid-template-columns: minmax(0, 1fr); gap: var(--content-steps-gap, 0.75rem); border-top: 0; }
/* The vertical and timeline layouts read the step padding, the marker size
   and the numeral's size (step 29b); blank is what each drew before. */
.cms-steps.cms-kind--vertical .cms-step { display: grid; grid-template-columns: var(--content-step-marker-size, 3rem) minmax(0, 1fr); column-gap: 1.25rem; align-items: start;
    padding: var(--content-step-padding, 1.25rem);
    border: var(--content-step-tile-border-width, 1px) solid var(--content-step-tile-border-colour, var(--content-border-colour, #e5e7eb)); border-radius: var(--content-step-tile-radius, var(--radius-panel, 0.75rem));
    background: var(--content-step-tile-bg, var(--content-card-bg, var(--content-bg-colour, #fff))); }
.cms-steps.cms-kind--vertical .cms-step::before { content: none; }
.cms-steps.cms-kind--vertical .cms-step__number { display: grid; place-items: center; width: var(--content-step-marker-size, 3rem); height: var(--content-step-marker-size, 3rem);
    border-radius: 50%; letter-spacing: 0; font-size: var(--content-step-number-size, 1rem);
    background: var(--content-step-marker-colour, var(--brand-primary-colour, #691EDA)); color: var(--content-step-number-colour, var(--text-primary-colour, #fff)); }
.cms-steps.cms-kind--vertical:not(.cms-content-step-number-style-italic, .cms-content-step-number-style-gradient) .cms-step:nth-child(2n) .cms-step__number { background: var(--content-step-marker-alt-colour, var(--content-step-marker-colour, var(--brand-primary-colour, #691EDA))); }
.cms-steps.cms-kind--vertical .cms-step__title { margin-top: 0; }
.cms-steps.cms-kind--vertical .cms-step:nth-child(2n) { padding: var(--content-step-padding, 1.25rem); }
/* An italic or gradient numeral on the vertical layout is drawn bare, not in a round. */
.cms-steps.cms-kind--vertical:is(.cms-content-step-number-style-italic, .cms-content-step-number-style-gradient) .cms-step__number { display: block; width: auto; height: auto;
    border-radius: 0; background-color: transparent; color: var(--content-step-number-colour, var(--brand-primary-colour, #691EDA)); font-size: var(--content-step-number-size, 1.5rem); }
/* Steps · timeline: one line down the left, a dot at each step. */
.cms-steps.cms-kind--timeline .cms-steps__list { grid-template-columns: minmax(0, 1fr); border-top: 0; margin-left: 0.3125rem;
    border-left: var(--content-step-path-value, var(--content-step-path-width, 2px) solid color-mix(in srgb, var(--content-step-path-colour, var(--brand-primary-colour, #691EDA)) 35%, transparent)); }
.cms-steps.cms-kind--timeline .cms-step { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr); padding: var(--content-step-padding, 0 0 1.75rem 1.5rem); }
.cms-steps.cms-kind--timeline .cms-step:nth-child(2n) { padding: var(--content-step-padding, 0 0 1.75rem 1.5rem); }
.cms-steps.cms-kind--timeline .cms-step:last-child { padding-bottom: 0; }
.cms-steps.cms-kind--timeline .cms-step::before { top: 0.375rem; left: calc(var(--content-step-marker-size, 0.875rem) / -2 - var(--content-step-path-width, 2px) / 2);
    width: var(--content-step-marker-size, 0.875rem); height: var(--content-step-marker-size, 0.875rem); }
.cms-steps.cms-kind--timeline .cms-step__number { font-size: var(--content-step-number-size, 1.375rem); letter-spacing: 0; line-height: 1.2; }
.cms-steps.cms-kind--timeline .cms-step__title { margin-top: 0; }

/* ---- Split --------------------------------------------------------------- */

.cms-split { display: grid; gap: var(--content-split-gap, 2.5rem); align-items: center; }
.cms-content-split-align-start .cms-split, .cms-split.cms-content-split-align-start { align-items: start; }
.cms-content-split-align-centre .cms-split, .cms-split.cms-content-split-align-centre { align-items: center; }
.cms-content-split-align-end .cms-split, .cms-split.cms-content-split-align-end { align-items: end; }
.cms-split--with-image { grid-template-columns: var(--cms-split-columns, minmax(0, 1.1fr) minmax(0, 1fr)); }
.cms-split--with-image.cms-split--left { grid-template-columns: var(--cms-split-columns-left, minmax(0, 1fr) minmax(0, 1.1fr)); }
.cms-split--left .cms-split__image { order: -1; }
.cms-split__body { margin: var(--content-split-body-space, 0.75rem 0 0); font-size: var(--content-split-body-size, 1.0625rem); line-height: var(--content-split-body-line-height, inherit); }
.cms-split .cms-kind__button { margin-top: var(--content-split-button-space, 1.5rem); }
/* `object-fit` is a no-op until a height bounds the picture (Assure's closing
   strip draws its mark at 34px, not as a half-width illustration). */
.cms-split__image { width: 100%; height: auto; max-height: var(--content-split-image-height, none); object-fit: contain;
    border-radius: var(--content-split-image-radius, var(--radius-panel, 0.75rem)); }
.cms-content-split-ratio-equal { --cms-split-columns: minmax(0, 1fr) minmax(0, 1fr); --cms-split-columns-left: minmax(0, 1fr) minmax(0, 1fr); }
.cms-content-split-ratio-wide-copy { --cms-split-columns: minmax(0, 3fr) minmax(0, 2fr); --cms-split-columns-left: minmax(0, 2fr) minmax(0, 3fr); }
.cms-content-split-ratio-wide-image { --cms-split-columns: minmax(0, 2fr) minmax(0, 3fr); --cms-split-columns-left: minmax(0, 3fr) minmax(0, 2fr); }
/* The image frame (Residual 18). */
.cms-content-split-image-frame-none .cms-split__image { border-radius: 0; }
.cms-content-split-image-frame-hard-shadow .cms-split__image { border-radius: 0; border: 2px solid var(--content-split-frame-colour, var(--brand-ink, #1d1b22));
    box-shadow: 14px 14px 0 var(--content-split-shadow-colour, var(--brand-primary-colour, #691EDA)); }
/* The offset falls away from the copy, so it mirrors when the picture is on the left (step 29b). */
.cms-content-split-image-frame-hard-shadow.cms-split--left .cms-split__image { box-shadow: -14px 14px 0 var(--content-split-shadow-colour, var(--brand-primary-colour, #691EDA)); }
.cms-content-split-image-frame-engraving .cms-split__image { border-radius: 0; padding: 0.5rem; border: 1px solid var(--content-split-frame-colour, var(--brand-ink, #1d1b22));
    outline: 1px solid var(--content-split-frame-colour, var(--brand-ink, #1d1b22)); outline-offset: -0.75rem; filter: grayscale(1) contrast(1.1); }
.cms-content-split-image-frame-blob .cms-split__image { border-radius: 58% 42% 55% 45% / 45% 55% 45% 55%; aspect-ratio: 1; object-fit: cover; }
.cms-content-split-image-frame-window .cms-split__image { border: 1px solid var(--content-split-frame-colour, var(--content-border-colour, #e5e7eb)); padding: 0.5rem;
    background: var(--content-bg-colour, #fff); box-shadow: 0 24px 48px rgba(10, 10, 10, 0.18); }
.cms-content-split-image-frame-tinted .cms-split__image { padding: 1rem; background: var(--content-split-frame-colour, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 12%, var(--content-bg-colour, #fff)))); }
/* Split · entry: a directory entry — the plate to one side, a hairline beneath. */
.cms-split.cms-kind--entry { align-items: start; padding-bottom: var(--content-band-padding, 2.5rem); border-bottom: 1px solid var(--content-border-colour, #e5e7eb); }
.cms-split.cms-kind--entry .cms-split__copy { padding: 1.5rem; border-radius: var(--radius-panel, 0.75rem); background: var(--content-tone-panel-bg, var(--content-bg-colour, #fff)); }
@media (max-width: 800px) {
    .cms-split--with-image, .cms-split--with-image.cms-split--left { grid-template-columns: minmax(0, 1fr); }
    .cms-split--left .cms-split__image { order: 0; }
}

/* ---- Quotes -------------------------------------------------------------- */

/* Quotes · grid (default): a panel per quote. */
.cms-quotes__grid { display: grid; gap: var(--content-quotes-gap, 1rem); margin-top: var(--content-quotes-grid-space, 1.25rem); grid-template-columns: var(--cms-quotes-columns, repeat(auto-fit, minmax(17rem, 1fr))); }
/* A band holding ONE quote is one column, whatever the columns setting says
   (DEV-167). The setting describes how a set of testimonials lays out; a
   single pull quote on a photograph was taking half the measure from it and
   running twice as deep as it should. Nothing to configure: one thing does
   not need columns. */
.cms-quotes .cms-quotes__grid:not(:has(.cms-quote + .cms-quote)) { --cms-quotes-columns: minmax(0, 1fr); }
.cms-content-quotes-columns-auto { --cms-quotes-columns: repeat(auto-fit, minmax(17rem, 1fr)); }
.cms-content-quotes-columns-1 { --cms-quotes-columns: minmax(0, 1fr); }
.cms-content-quotes-columns-2 { --cms-quotes-columns: repeat(2, minmax(0, 1fr)); }
.cms-content-quotes-columns-3 { --cms-quotes-columns: repeat(3, minmax(0, 1fr)); }
.cms-content-quotes-columns-4 { --cms-quotes-columns: repeat(4, minmax(0, 1fr)); }
.cms-content-quote-align-start .cms-quote { text-align: left; }
.cms-content-quote-align-centre .cms-quote { text-align: center; }
.cms-content-quote-align-end .cms-quote { text-align: right; }
.cms-quote { display: flex; flex-direction: column; gap: var(--content-quote-text-space, 1.25rem); margin: 0;
    padding: var(--content-quote-padding, 1.5rem); border-radius: var(--content-quote-radius, var(--radius-panel, 0.75rem));
    border: 1px solid var(--content-quote-border-colour, var(--content-border-colour, #e5e7eb)); background: var(--content-quote-bg, var(--content-bg-colour, #fff));
    box-shadow: var(--content-quote-shadow, none); }
/* ---- The speaker's portrait (DEV-167) -----------------------------------
   Above the words by default; `beside` puts it in a row with them, and
   `with-source` drops it down beside the name. The quote's own flex gap
   spaces the rows, so the space setting is the portrait's margin over it. */
.cms-quote__image { display: block; flex: none; width: var(--content-quote-image-size, 4rem); height: var(--content-quote-image-size, 4rem);
    object-fit: cover; border-radius: 50%; margin-bottom: var(--content-quote-image-space, 0); }
.cms-content-quote-image-shape-square .cms-quote__image { border-radius: var(--content-quote-radius, var(--radius-control, 0.375rem)); }
/* Beside, and with-source, place the three parts explicitly: the figure's
   children are picture, words, speaker in that order, and auto-placement
   would put the words beside the picture in both. */
.cms-content-quote-image-position-beside .cms-quote { display: grid; grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--content-quote-image-space, 1.25rem); align-items: start; }
.cms-content-quote-image-position-beside .cms-quote__image { grid-column: 1; grid-row: 1 / span 2; margin-bottom: 0; }
.cms-content-quote-image-position-beside .cms-quote__text { grid-column: 2; grid-row: 1; }
.cms-content-quote-image-position-beside .cms-quote__source { grid-column: 2; grid-row: 2; }
.cms-content-quote-image-position-with-source .cms-quote { display: grid; grid-template-columns: auto minmax(0, 1fr);
    column-gap: var(--content-quote-image-space, 1rem); }
.cms-content-quote-image-position-with-source .cms-quote__text { grid-column: 1 / -1; grid-row: 1; }
.cms-content-quote-image-position-with-source .cms-quote__image { grid-column: 1; grid-row: 2; align-self: center; margin-bottom: 0; }
.cms-content-quote-image-position-with-source .cms-quote__source { grid-column: 2; grid-row: 2; align-self: center; }
.cms-quote__text { margin: 0; font-size: var(--content-quote-text-size, 1.0625rem); font-weight: var(--content-quote-text-weight, 500);
    line-height: var(--content-quote-text-line-height, inherit); }
.cms-quote__source { margin-top: auto; }
/* The speaker straight after the words rather than at the panel's foot. */
.cms-content-quote-source-position-follow .cms-quote__source { margin-top: 0; }
.cms-quote__name { display: block; font-weight: var(--content-quote-name-weight, 600); font-size: var(--content-quote-name-size, 0.9375rem);
    text-transform: var(--content-quote-name-transform, none); letter-spacing: var(--content-quote-name-letter-spacing, normal);
    color: var(--content-quote-name-colour, inherit); }
.cms-content-quote-name-transform-small-caps .cms-quote__name { text-transform: none; font-variant: small-caps; }
.cms-quote__role { display: block; font-size: var(--content-quote-role-size, 0.875rem); color: var(--content-quote-role-colour, color-mix(in srgb, currentColor 70%, transparent)); }
.cms-content-quote-text-font-heading .cms-quote__text { font-family: var(--header-font-family, inherit); }
.cms-content-quote-text-style-italic .cms-quote__text { font-style: italic; }
.cms-content-quote-text-style-normal .cms-quote__text { font-style: normal; }
/* Quotes · pull: one centred column (or two, columns=2) of large, quoted lines. */
/* The pull column is held to the quotes band measure when one is set (step 29b: a literal 46rem the measure could not widen). */
.cms-quotes.cms-kind--pull .cms-quotes__grid { grid-template-columns: var(--cms-quotes-columns, minmax(0, 1fr)); gap: var(--content-quotes-gap, 3rem); max-width: var(--content-quote-pull-measure, var(--content-quotes-band-measure, 46rem)); margin-inline: auto; }
.cms-quotes.cms-kind--pull.cms-quotes--columns-2 .cms-quotes__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: none; }
.cms-quotes.cms-kind--pull .cms-quote { padding: 0; border: 0; background: transparent; text-align: center; box-shadow: none; }
/* The pull variant's own type (DEV-167): its size, face, measure, alignment
   and the speaker's ink are separate from the quote settings, because those
   dress the testimonial cards on the same presence. Every one falls back to
   what the pull quote drew before, so blank changes nothing. */
.cms-quotes.cms-kind--pull .cms-quote__text { font-size: var(--content-quote-pull-size, var(--content-quote-text-size, clamp(1.375rem, 2.8vw, 2rem))); font-style: italic;
    font-weight: var(--content-quote-text-weight, 400); line-height: var(--content-quote-text-line-height, 1.35); }
.cms-content-quote-pull-font-heading .cms-quotes.cms-kind--pull .cms-quote__text { font-family: var(--header-font-family, inherit); font-style: normal; }
.cms-content-quote-pull-font-body .cms-quotes.cms-kind--pull .cms-quote__text { font-family: var(--font-family, inherit); }
.cms-content-quote-pull-align-left .cms-quotes.cms-kind--pull :is(.cms-quote, .cms-quote__text, .cms-quote__source) { text-align: left; justify-content: flex-start; }
.cms-content-quote-pull-align-centre .cms-quotes.cms-kind--pull :is(.cms-quote, .cms-quote__text, .cms-quote__source) { text-align: center; justify-content: center; }
/* The speaker on a pull quote inherits the band's colour rather than the
   card's ink, so a quote on a dark or photographic band is readable without
   a rule of its own; a setting overrides it. */
.cms-quotes.cms-kind--pull :is(.cms-quote__name, .cms-quote__role) { color: var(--content-quote-pull-source-colour, inherit); }
.cms-quotes.cms-kind--pull .cms-quote__text > :first-child::before { content: '\201C'; color: var(--content-quote-marks-colour, var(--brand-primary-colour, #691EDA)); }
.cms-quotes.cms-kind--pull .cms-quote__text > :last-child::after { content: '\201D'; color: var(--content-quote-marks-colour, var(--brand-primary-colour, #691EDA)); }
/* Quotes · bubbles: the quote in a speech bubble, its speaker beneath the tail. */
.cms-quotes.cms-kind--bubbles .cms-quotes__grid { gap: var(--content-quotes-gap, 1.75rem); }
/* The bubble is the words, not the panel, so it reads the quote panel's
   padding, radius and shadow (step 29b). */
.cms-quotes.cms-kind--bubbles .cms-quote { padding: 0; border: 0; background: transparent; gap: var(--content-quote-text-space, 1.375rem); box-shadow: none; }
.cms-quotes.cms-kind--bubbles .cms-quote__text { position: relative; padding: var(--content-quote-padding, 1.5rem); border-radius: var(--content-quote-radius, var(--radius-panel, 1.5rem));
    box-shadow: var(--content-quote-shadow, none);
    background: var(--content-quote-bg, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 12%, var(--content-bg-colour, #fff)))); }
.cms-quotes.cms-kind--bubbles .cms-quote__text::after { content: ''; position: absolute; left: 2rem; bottom: -0.8125rem;
    border: 0.875rem solid transparent; border-bottom: 0;
    border-top-color: var(--content-quote-bg, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 12%, var(--content-bg-colour, #fff)))); }
.cms-quotes.cms-kind--bubbles .cms-quote__source { margin-top: 0; padding-left: 1.5rem; }
.cms-quotes.cms-kind--bubbles .cms-quote__name { color: var(--content-quote-name-colour, var(--content-quote-marks-colour, var(--brand-primary-colour, #691EDA))); }
/* The panel, by content-quote-panel: ruled, card, glass, bubble, none. */
.cms-content-quote-panel-ruled .cms-quote { border: 0; border-top: 2px solid var(--content-quote-border-colour, currentColor); border-radius: 0; background: transparent; }
.cms-content-quote-panel-card .cms-quote { border-color: transparent; box-shadow: var(--content-quote-shadow, 0 8px 24px rgba(10, 10, 10, 0.1)); background: var(--content-quote-bg, var(--content-bg-colour, #fff)); }
/* Glass takes the quote ground and edge when they are set (step 29b); blank tints with the text colour. */
.cms-content-quote-panel-glass .cms-quote { background: var(--content-quote-bg, color-mix(in srgb, currentColor 8%, transparent));
    border-color: var(--content-quote-border-colour, color-mix(in srgb, currentColor 18%, transparent)); backdrop-filter: blur(8px); }
.cms-content-quote-panel-none .cms-quote { border: 0; background: transparent; padding: 0; box-shadow: none; }
.cms-content-quote-panel-bubble .cms-quote__text { position: relative; padding: var(--content-quote-padding, 1.5rem); border-radius: var(--content-quote-radius, var(--radius-panel, 1.5rem));
    background: var(--content-quote-bg, var(--content-bg-colour, #fff)); box-shadow: var(--content-quote-shadow, 0 8px 24px rgba(10, 10, 10, 0.1)); }
.cms-content-quote-panel-bubble .cms-quote { border: 0; background: transparent; padding: 0; box-shadow: none; }

/* ---- Band (call to action) ----------------------------------------------- */

.cms-band { display: flex; flex-wrap: wrap; gap: var(--content-band-cta-gap, 1.5rem) var(--content-band-cta-gap, 2rem); justify-content: space-between; align-items: center;
    padding: var(--content-band-cta-padding, clamp(1.75rem, 4vw, 3rem)); border-radius: var(--content-band-cta-radius, var(--radius-panel, 1rem));
    background: var(--content-band-cta-bg, var(--brand-primary-colour, #691EDA)); color: var(--text-primary-colour, #fff);
    border: var(--content-band-cta-frame-value, 0); box-shadow: var(--content-band-cta-shadow-value, none); }
/* Residual 20: the copy no longer flex-grows, so a long heading wraps instead of pushing the buttons down. */
.cms-band__copy { flex: 0 1 auto; max-width: var(--content-band-cta-copy-measure, 40rem); }
.cms-band__heading { margin: 0; font-size: var(--content-band-cta-heading-size, clamp(1.5rem, 3vw, 2.25rem));
    font-weight: var(--content-band-cta-heading-weight, 700); line-height: var(--content-band-cta-heading-line-height, 1.15);
    text-transform: var(--content-band-cta-heading-transform, none); letter-spacing: var(--content-band-cta-heading-letter-spacing, var(--header-letter-spacing, normal)); color: inherit; }
.cms-content-band-cta-heading-transform-small-caps .cms-band__heading { text-transform: none; font-variant: small-caps; }
/* The body is the band's text at 90% unless it has a colour of its own, and
   takes its own leading (step 29b: a fixed opacity dimmed any colour). */
.cms-band__body { margin-top: var(--content-band-cta-body-space, 0.625rem); font-size: var(--content-band-cta-body-size, inherit);
    color: var(--content-band-cta-body-colour, color-mix(in srgb, currentColor 90%, transparent));
    line-height: var(--content-band-cta-body-line-height, var(--content-body-line-height, var(--content-line-height, 1.65))); }
.cms-band__body a { color: inherit; }
.cms-band__actions { display: flex; flex-wrap: wrap; gap: var(--content-band-cta-actions-gap, 0.75rem); }
/* The band's first button: white on the brand ground by default, or the
   band's own button pair (step 29b) — the literal pair was right only on the
   default brand ground. */
.cms-band__button { border-color: var(--content-band-cta-button-bg, var(--text-primary-colour, #fff));
    background: var(--content-band-cta-button-bg, var(--text-primary-colour, #fff)); color: var(--content-band-cta-button-text, var(--brand-primary-colour, #691EDA)); }
.cms-band__button:hover { background: var(--content-band-cta-button-bg, var(--text-primary-colour, #fff)); color: var(--content-band-cta-button-text, var(--brand-primary-colour, #691EDA));
    border-color: var(--content-band-cta-button-bg, var(--text-primary-colour, #fff)); }
.cms-band__button--ghost { background: transparent; color: inherit; }
.cms-band__button--ghost:hover { background: transparent; color: inherit; }
.cms-band--centre { flex-direction: column; text-align: center; justify-content: center; }
.cms-content-band-cta-align-centre .cms-band, .cms-band.cms-content-band-cta-align-centre { flex-direction: column; text-align: center; justify-content: center; }
/* Centred, the copy spans its measure (centred in the band) rather than
   shrinking to its words, and the buttons centre whichever way the band was
   centred — by its field or by content-band-cta-align (step 29b). */
.cms-band--centre .cms-band__copy, .cms-content-band-cta-align-centre .cms-band__copy, .cms-band.cms-content-band-cta-align-centre .cms-band__copy { width: 100%; margin-inline: auto; }
.cms-band--centre .cms-band__actions, .cms-content-band-cta-align-centre .cms-band__actions, .cms-band.cms-content-band-cta-align-centre .cms-band__actions { justify-content: center; }
.cms-content-band-cta-frame-outline { --content-band-cta-frame-value: 2px solid var(--content-band-cta-frame-colour, var(--text-primary-colour, #fff)); }
.cms-content-band-cta-frame-shadow { --content-band-cta-shadow-value: 0 24px 48px color-mix(in srgb, var(--content-band-cta-frame-colour, var(--brand-primary-colour, #691EDA)) 35%, transparent); }
.cms-content-band-cta-frame-none { --content-band-cta-frame-value: 0; --content-band-cta-shadow-value: none; }
/* A band on a chosen tone keeps the tone's colours rather than the brand's. */
.cms-band.cms-kind--tone-ink { background: var(--content-tone-ink-bg, var(--brand-ink, #1d1b22)); color: var(--content-tone-ink-text, #fff); }
.cms-band.cms-kind--tone-panel { background: var(--content-tone-panel-bg, var(--content-bg-colour, #fff)); color: var(--content-tone-panel-text, var(--content-text-colour, #111827)); }
.cms-band.cms-kind--tone-tint { background: var(--content-tone-tint-bg, var(--brand-primary-soft, color-mix(in srgb, var(--brand-primary-colour, #691EDA) 8%, var(--content-bg-colour, #fff)))); color: var(--content-tone-tint-text, var(--content-text-colour, #111827)); }
.cms-band.cms-kind--tone-panel .cms-band__button, .cms-band.cms-kind--tone-tint .cms-band__button {
    background: var(--content-band-cta-button-bg, var(--button-primary-bg, var(--brand-primary-colour, #691EDA))); color: var(--content-band-cta-button-text, var(--button-primary-fg, var(--text-primary-colour, #fff)));
    border-color: var(--content-band-cta-button-bg, var(--button-primary-bg, var(--brand-primary-colour, #691EDA))); }

/* ---- Text --------------------------------------------------------------- */

/* A Text block is drawn by cms::presence.blocks, not by a kind view: a plain
   heading over prose. Its type is the `content.text` group's; blank keeps what
   that view drew. The band's own style element sits after this sheet, so the
   heading's properties are read there and only the pieces this sheet can hold
   (the prose, and the case a custom property cannot carry) are here. */
.cms-brochure__band--text .cms-brochure__body { font-size: var(--content-text-body-size, inherit);
    line-height: var(--content-text-body-line-height, var(--content-body-line-height, var(--content-line-height, 1.65))); }
.cms-content-text-heading-transform-small-caps .cms-brochure__heading { text-transform: none; font-variant: small-caps; }

/* ---- Carousel (DEV-167) --------------------------------------------------
   A layout, not a kind: a cards, quotes or stats block that asked for one
   keeps its markup and its grid, and the script turns that grid into a
   track. Every rule that makes it horizontal hangs off `--ready`, which only
   the script adds, so with no JavaScript the block is the grid it has always
   been and the controls row (empty and hidden in the markup) never appears.

   The chrome reads the content.carousel settings; blank draws the neutral
   default each rule carries, as everywhere else. */
.cms-carousel--ready .cms-carousel__track {
    display: flex;
    overflow-x: auto;
    /* A scrolling box clips what overflows it, and a slide's shadow is the
       first casualty — a card carousel drew a hard edge where the shadow was
       cut. Room inside, taken back outside, so the slides sit exactly where
       the grid put them. */
    padding: var(--cms-carousel-room, 1.25rem);
    margin: calc(-1 * var(--cms-carousel-room, 1.25rem));
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /* The scrollbar is chrome the controls replace; it is still reachable by
       keyboard and by touch. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* A focus ring on the track, which is focusable so a keyboard can page
       through it. */
    outline-offset: 4px;
}
.cms-carousel--ready .cms-carousel__track::-webkit-scrollbar { display: none; }
.cms-carousel--ready .cms-carousel__track > * {
    /* One slide per view unless a class says otherwise; the gap is the
       kind's own, so a carousel is spaced like the grid it replaced. */
    flex: 0 0 var(--cms-carousel-slide, 100%);
    scroll-snap-align: start;
    min-width: 0;
}
@media (prefers-reduced-motion: reduce) {
    .cms-carousel--ready .cms-carousel__track { scroll-behavior: auto; }
}

/* How many show at once. Two slides at a phone width is the most that reads,
   so every count above two narrows to one — a site that wants two says so
   with --slides-mobile-2. */
.cms-carousel--slides-2.cms-carousel--ready .cms-carousel__track > * { --cms-carousel-slide: calc((100% - 1 * var(--cms-carousel-gap, 1rem)) / 2); }
.cms-carousel--slides-3.cms-carousel--ready .cms-carousel__track > * { --cms-carousel-slide: calc((100% - 2 * var(--cms-carousel-gap, 1rem)) / 3); }
.cms-carousel--slides-4.cms-carousel--ready .cms-carousel__track > * { --cms-carousel-slide: calc((100% - 3 * var(--cms-carousel-gap, 1rem)) / 4); }
.cms-carousel--slides-5.cms-carousel--ready .cms-carousel__track > * { --cms-carousel-slide: calc((100% - 4 * var(--cms-carousel-gap, 1rem)) / 5); }
.cms-carousel--slides-6.cms-carousel--ready .cms-carousel__track > * { --cms-carousel-slide: calc((100% - 5 * var(--cms-carousel-gap, 1rem)) / 6); }
/* The gap each kind's grid already uses, so the two layouts match. */
.cms-cards.cms-carousel { --cms-carousel-gap: var(--content-cards-gap, 1rem); }
.cms-quotes.cms-carousel { --cms-carousel-gap: var(--content-quotes-gap, 1rem); }
.cms-stats.cms-carousel { --cms-carousel-gap: var(--content-stats-gap, 1rem); }

@media (max-width: 720px) {
    .cms-carousel--ready .cms-carousel__track > * { --cms-carousel-slide: 100%; }
    .cms-carousel--slides-mobile-2.cms-carousel--ready .cms-carousel__track > * { --cms-carousel-slide: calc((100% - 1 * var(--cms-carousel-gap, 1rem)) / 2); }
}

/* The controls row: arrows either side of the dots, under the track by
   default. `outside` pulls the arrows out to the band's gutter; `inside`
   floats them over the track's edges. */
.cms-carousel__controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--content-carousel-control-gap, 1rem);
    margin-top: var(--content-carousel-control-space, 1.5rem);
}
/* The controls are real buttons, and styles.css carries
   `button { border-radius: var(--buttons-border-radius) !important }` for the
   whole estate — so a round control has to say so just as loudly, or a site
   with square buttons gets square dots. The rest of the rule is ordinary. */
.cms-carousel__arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--content-carousel-control-size, 2.5rem);
    height: var(--content-carousel-control-size, 2.5rem);
    border: 1px solid var(--content-carousel-control-border-colour, var(--content-border-colour, #e5e7eb));
    border-radius: var(--content-carousel-control-radius, 999px) !important;
    background: var(--content-carousel-control-bg, transparent);
    color: var(--content-carousel-control-colour, inherit);
    cursor: pointer;
    line-height: 1;
}
.cms-carousel__arrow:disabled { opacity: 0.35; cursor: default; }
.cms-carousel__dots { display: flex; align-items: center; gap: var(--content-carousel-dot-gap, 0.5rem); }
.cms-carousel__dot {
    width: var(--content-carousel-dot-size, 0.5rem);
    height: var(--content-carousel-dot-size, 0.5rem);
    padding: 0;
    border: 0;
    /* A dot is round by definition — see the arrow above for the !important. */
    border-radius: 999px !important;
    background: var(--content-carousel-dot-colour, var(--content-border-colour, #e5e7eb));
    cursor: pointer;
}
.cms-carousel__dot--current { background: var(--content-carousel-dot-active-colour, var(--brand-primary-colour, #691EDA)); }

/* content-carousel-control-position: where the arrows sit. */
.cms-content-carousel-control-position-inside .cms-carousel--ready { position: relative; }
.cms-content-carousel-control-position-inside .cms-carousel__arrow {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 1;
    background: var(--content-carousel-control-bg, var(--content-bg-colour, #fff));
}
.cms-content-carousel-control-position-inside .cms-carousel__arrow--prev { left: 0; }
.cms-content-carousel-control-position-inside .cms-carousel__arrow--next { right: 0; }
.cms-content-carousel-control-position-outside .cms-carousel__controls { justify-content: space-between; }
