/**
 * Page chrome: header, footer and spacing between template parts.
 * Loaded on every page (and in the editor).
 */

/* Template parts sit flush; the footer keeps a section gap above it. */
.wp-site-blocks > footer {
	margin-block-start: var(--wp--preset--spacing--80);
}

/*
 * Sticky header offset: the admin bar (when logged in) plus the header row.
 * Other sticky elements and in-page anchors stop below it.
 */
:root {
	--rowww-header-height: 4.75rem;
	--rowww-sticky-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--rowww-header-height));
}

/* Phones: the slimmer header row (`custom.header.padding-block-mobile`). */
@media (max-width: 781px) {

	:root {
		--rowww-header-height: 3.375rem;
	}
}

/* On phones the admin bar scrolls away, so it does not count. */
@media (max-width: 600px) {

	:root {
		--rowww-sticky-top: var(--rowww-header-height);
	}
}

/* In-page anchors (e.g. #design) land below the header with breathing room. */
html {
	scroll-padding-top: calc(var(--rowww-sticky-top) + var(--wp--preset--spacing--40));
}

/* In-page links (tables of contents, #anchors) scroll smoothly; native,
   no JS. */
@media (prefers-reduced-motion: no-preference) {

	html {
		scroll-behavior: smooth;
	}
}

/*
 * Header: sticky on every screen, above page content (hero glows, mega menu
 * panel). Apple-style frosted glass: a translucent, blurred backdrop that
 * fades in during the first ~120px of scrolling (scroll-driven, no JS;
 * without support it is simply always on). The blur lives on ::before, not
 * on the header: a backdrop-filter would trap the fixed mobile menu overlay
 * inside the header box.
 */
.wp-site-blocks > header {
	position: sticky;
	z-index: 100;
	top: var(--wp-admin--admin-bar--height, 0px);
}

@media (max-width: 600px) {

	.wp-site-blocks > header {
		top: 0;
	}
}

/* Logo-only header (contact, thank-you pages): scrolls away with the page,
   no glass, no slimming; anchors only clear the admin bar. */
.wp-site-blocks > header:has(.rowww-site-header.is-static) {
	position: relative;
}

.wp-site-blocks > header:has(.rowww-site-header.is-static)::before {
	content: none;
}

:root:has(.rowww-site-header.is-static) {
	--rowww-sticky-top: var(--wp-admin--admin-bar--height, 0px);
}

@media (max-width: 600px) {

	:root:has(.rowww-site-header.is-static) {
		--rowww-sticky-top: 0px;
	}
}

.wp-site-blocks > header::before {
	content: "";
	position: absolute;
	z-index: -1;
	inset: 0;
	background: color-mix(in srgb, var(--wp--preset--color--base) 70%, transparent);
	-webkit-backdrop-filter: saturate(180%) blur(20px);
	backdrop-filter: saturate(180%) blur(20px);
	pointer-events: none;
}

@supports (animation-timeline: scroll()) {

	@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {

		.wp-site-blocks > header::before {
			animation: rowww-header-glass linear both;
			animation-timeline: scroll(root);
			animation-range: 0 120px;
		}
	}
}

@keyframes rowww-header-glass {

	from {
		opacity: 0;
	}
}

/*
 * The sticky header slims down while scrolling: less padding and a smaller
 * logo (same scroll range as the glass); on phones only the logo shrinks.
 * Padding is layout, so animating it re-lays out the page on every scroll
 * frame, which stutters on phones; opacity and transform do not.
 * Without scroll-driven animations it simply keeps its full height.
 */
@supports (animation-timeline: scroll()) {

	@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {

		.rowww-site-header:not(.is-static) {
			animation: rowww-header-slim linear both;
			animation-timeline: scroll(root);
			animation-range: 0 120px;
		}
	}

	@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {

		.rowww-site-header:not(.is-static) .wp-block-site-logo {
			transform-origin: left center;
			animation: rowww-logo-slim linear both;
			animation-timeline: scroll(root);
			animation-range: 0 120px;
		}
	}
}

@keyframes rowww-header-slim {

	to {
		padding-block: var(--wp--preset--spacing--10);
	}
}

@keyframes rowww-logo-slim {

	to {
		transform: scale(var(--rowww-logo-scale-sticky));
	}
}

/*
 * Header row padding (`custom.header`): a slimmer bar on phones.
 * Scrolled logo size: a little larger on desktop.
 */
.rowww-site-header {
	padding-block: var(--wp--custom--header--padding-block);
	--rowww-logo-scale-sticky: var(--wp--custom--header--logo-scale-sticky);
}

@media (min-width: 1024px) {

	.rowww-site-header {
		--rowww-logo-scale-sticky: var(--wp--custom--header--logo-scale-sticky-desktop);
	}
}

.rowww-site-header__inner {
	position: relative; /* Anchor for the centred mega menu panel. */
	gap: var(--wp--preset--spacing--40);
}

/*
 * Header sizes (`custom.header` in theme.json): logo width, smaller on
 * phones, and the shared text size of the menu and the contact button.
 */
.rowww-site-header .wp-block-site-logo img {
	width: var(--wp--custom--header--logo-width);
	height: auto;
}

.rowww-main-nav,
.rowww-site-header__actions .wp-block-button__link {
	font-size: var(--wp--custom--header--font-size);
}

@media (max-width: 781px) {

	.rowww-site-header {
		padding-block: var(--wp--custom--header--padding-block-mobile);
	}

	.rowww-site-header .wp-block-site-logo img {
		width: var(--wp--custom--header--logo-width-mobile);
	}
}

/*
 * Desktop: let the mega menu panel position against the header row by
 * making the navigation wrappers between them non-positioned.
 */
@media (min-width: 1024px) {

	.rowww-site-header__inner :is(.wp-block-navigation, .wp-block-navigation__responsive-container:not(.is-menu-open), .wp-block-navigation__responsive-dialog, .wp-block-navigation__responsive-container-content, .wp-block-navigation__container) {
		position: static;
	}
}

/*
 * Contact button: on hover a lime fill sweeps in from the left and an arrow
 * slides out. The fill sits behind the label (isolated stacking context).
 */
.rowww-site-header__actions .wp-block-button__link {
	position: relative;
	isolation: isolate;
	display: inline-flex;
	align-items: center;
	overflow: hidden;
	padding: 0.5rem 1.25rem;
	font-weight: 400;
	white-space: nowrap;
}

.rowww-site-header__actions .wp-block-button__link::before {
	content: "";
	position: absolute;
	z-index: -1;
	inset: 0;
	background-color: var(--wp--preset--color--cta);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 450ms cubic-bezier(0.22, 1, 0.36, 1);
}

.rowww-site-header__actions .wp-block-button__link::after {
	content: "→";
	display: inline-block;
	width: 0;
	opacity: 0;
	transform: translateX(-0.5em);
	transition: width 350ms cubic-bezier(0.22, 1, 0.36, 1), margin 350ms cubic-bezier(0.22, 1, 0.36, 1), opacity 250ms ease, transform 350ms cubic-bezier(0.22, 1, 0.36, 1);
}

.rowww-site-header__actions .wp-block-button__link:is(:hover, :focus-visible)::before {
	transform: scaleX(1);
}

/* On the lime fill the label turns dark (the outline style would keep it
   white) and the edge goes. Stronger than the secondary hover rule. */
.rowww-site-header__actions .wp-block-button.is-style-secondary .wp-block-button__link:is(:hover, :focus-visible) {
	background-color: transparent;
	box-shadow: none;
	color: var(--wp--preset--color--base);
}

.rowww-site-header__actions .wp-block-button__link:is(:hover, :focus-visible)::after {
	width: 1em;
	margin-inline-start: 0.35em;
	opacity: 1;
	transform: none;
}

/*
 * The main menu needs ~1000px in one line; core only switches to the
 * overlay below 600px, so tablets and small laptops use the overlay too.
 */
@media (min-width: 600px) and (max-width: 1023px) {

	.rowww-main-nav .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	.rowww-main-nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

@media (max-width: 1023px) {

	/* Logo, contact button, then the menu toggle. */
	.rowww-site-header__inner > .wp-block-navigation {
		order: 3;
	}

	.rowww-site-header__inner > .rowww-site-header__actions {
		margin-inline-start: auto;
	}

	.rowww-site-header__actions .wp-block-button__link {
		padding: 0.375rem 0.875rem;
	}
}

/* Footer */
@media (max-width: 781px) {

	/* Phones: every footer column (services by category, company) stacked. */
	.rowww-site-footer .wp-block-rowww-service-index {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Bottom bar: social icons, legal links and copyright one under another. */
	.rowww-site-footer__bottom > .wp-block-group {
		flex-direction: column;
		align-items: flex-start;
	}
}

.rowww-footer-heading {
	margin-block: 0 var(--wp--preset--spacing--60);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	line-height: var(--wp--custom--line-height--base);
}

.rowww-site-footer .wp-block-site-tagline {
	max-width: 18rem;
}

.rowww-footer-menu .wp-block-navigation-item__content:hover,
.rowww-footer-menu .wp-block-navigation-item__content:focus-visible,
.rowww-legal-menu .wp-block-navigation-item__content:hover,
.rowww-legal-menu .wp-block-navigation-item__content:focus-visible {
	color: var(--wp--preset--color--contrast);
}

.rowww-site-footer .wp-block-social-links .wp-social-link a {
	padding: 0;
}

/* Card titles in post grids: no underline until hover. */
.rowww-card-title a {
	text-decoration: none;
}

.rowww-card-title a:hover,
.rowww-card-title a:focus-visible {
	text-decoration: underline;
}

/*
 * Page sections (patterns `rowww/section-*`): a large gap between sections,
 * and a narrower measure for section headings and intros.
 */
.rowww-section {
	margin-block-start: var(--wp--preset--spacing--80);
}

/* A page that opens with a section (legal pages, sitemap): the flow layout
   drops the first child's top margin, which put the breadcrumbs right
   against the header. Same start as the other sub pages. */
main > .rowww-section:first-child,
main > .wp-block-post-content:first-child > .rowww-section:first-child {
	padding-block-start: var(--wp--preset--spacing--70);
}

/* Lines of even length (e.g. a heading whose accent words sit on their
   own line). */
.rowww-balance {
	text-wrap: balance;
}

.rowww-section .rowww-measure {
	max-width: 36rem;
	text-wrap: pretty;
}

/* Headings are larger than the text, so their measure is wider. */
.rowww-section :is(h1, h2).rowww-measure {
	max-width: 42rem;
}

/* Every hero: a calmer glow (as first set on the home page), so the media
   and the title lead. */
.wp-block-rowww-hero {
	--rowww-glow-strength: 0.6;
}

/* A statement section (one large claim) gets a bit more air around it. */
.rowww-section:has(> .is-style-statement) {
	padding-block: var(--wp--preset--spacing--60);
}

/*
 * Aurora: a softer version of the hero glow behind a section (decorative).
 * Add `rowww-aurora` to a group, plus `is-aurora-left` to put the light on
 * the left. The glow may reach past the section.
 *
 * Glows (aurora, hero) are clipped sideways by the page wrapper, never by
 * `main` or the hero: Safari also clips vertically with `overflow-x: clip`,
 * which cut the hero light off at the hero's top edge, so the header sat on
 * a black bar. The wrapper's top is the page top, so nothing is lost there.
 * Fixed elements (mobile menu, dialogs) are not clipped by it.
 */
.wp-site-blocks,
.editor-styles-wrapper {
	overflow-x: clip;
}

.rowww-aurora {
	position: relative;
	isolation: isolate;
}

.rowww-aurora::before,
.rowww-aurora::after {
	content: "";
	position: absolute;
	z-index: -1;
	top: 50%;
	left: 85%;
	width: min(100vw, 66rem);
	aspect-ratio: 1;
	border-radius: 50%;
	background: radial-gradient(circle closest-side, color-mix(in srgb, var(--rowww-accent-end) 70%, transparent), color-mix(in srgb, var(--rowww-accent-end) 41%, transparent) 25%, color-mix(in srgb, var(--rowww-accent-end) 18%, transparent) 50%, color-mix(in srgb, var(--rowww-accent-end) 6%, transparent) 75%, transparent);
	opacity: 0.32;
	transform: translate(-50%, -50%);
	pointer-events: none;
}

.rowww-aurora::after {
	top: 70%;
	left: 100%;
	width: min(76vw, 50rem);
	background: radial-gradient(circle closest-side, color-mix(in srgb, var(--rowww-accent-start) 70%, transparent), color-mix(in srgb, var(--rowww-accent-start) 41%, transparent) 25%, color-mix(in srgb, var(--rowww-accent-start) 18%, transparent) 50%, color-mix(in srgb, var(--rowww-accent-start) 6%, transparent) 75%, transparent);
	opacity: 0.4;
}

.rowww-aurora.is-aurora-left::before {
	left: 15%;
}

.rowww-aurora.is-aurora-left::after {
	left: 0;
}

/* Phones: a wider spread across the narrow screen. */
@media (max-width: 781px) {

	.rowww-aurora::before {
		width: 80vw;
	}

	.rowww-aurora::after {
		width: 60vw;
	}
}

/*
 * Sticky column (e.g. the FAQ heading): stays in view while the column next
 * to it scrolls. Only side by side; stacked columns scroll normally.
 */
@media (min-width: 782px) {

	.rowww-sticky {
		position: sticky;
		top: calc(var(--rowww-sticky-top) + var(--wp--preset--spacing--40));
		align-self: flex-start;
	}
}

/*
 * Personal CTA right after a section: a clear gap above it, between the
 * in-section and the section spacing (it reads as its own step, not as a
 * part of the section above).
 */
.rowww-section + .rowww-personal-cta {
	margin-block-start: calc((var(--wp--preset--spacing--70) + var(--wp--preset--spacing--80)) / 2) !important; /* Beats the pattern's inline margin. */
}

/* A CTA that is a section of its own keeps the normal section gap. */
.rowww-section + .rowww-personal-cta.rowww-section {
	margin-block-start: var(--wp--preset--spacing--80) !important;
}

/*
 * The line under the FAQ questions ("Did not find your question? Ask us
 * directly."): its link is the call to action, white and underlined in the
 * muted sentence instead of a separate button.
 */
.rowww-faq-cta:not(.is-style-card) > p a {
	color: var(--wp--preset--color--contrast);
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

.rowww-faq-cta:not(.is-style-card) > p a:hover {
	color: var(--wp--preset--color--cta);
}

/*
 * The personal CTA reads as a message from the contact person, laid out like
 * a chat: the name and title on a small line, below it the message in a
 * bubble with the photo beside its lower corner (the corner next to the photo
 * is the tail), and the button under the bubble as the reply. A grid places
 * the photo, the name and the title out of their nested groups
 * (`display: contents`), so the saved pages change too. The message is the
 * paragraph, or a `rowww-bubble` group where it is more than one block. The
 * card next to the pricing FAQ does the same in its narrow column.
 */
.wp-block-group.wp-block-group.rowww-personal-cta,
.wp-block-group.rowww-faq-cta.is-style-card {
	--rowww-avatar: 2.75rem;
	--rowww-avatar-gap: 0.875rem;
	--rowww-bubble-corner: 0.375rem;

	display: grid;
	grid-template-columns: calc(var(--rowww-avatar) + var(--rowww-avatar-gap)) auto minmax(0, 1fr);
	grid-template-areas:
		".     name   title"
		"photo bubble bubble"
		".     action action";
	align-items: baseline;
	gap: var(--wp--preset--spacing--20) 0;
	padding: 0;
	border: 0;
	background: none;
	box-shadow: none;
}

.wp-block-group.wp-block-group.rowww-personal-cta {
	max-width: var(--wp--style--global--content-size);
	margin-inline: auto;
}

.wp-block-group.rowww-faq-cta.is-style-card {
	--rowww-avatar: 2.5rem;
}

:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble),
:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-group {
	display: contents;
}

/* Photo: small, beside the bubble's lower corner, with an "online" dot. */
:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-image {
	position: relative;
	grid-area: photo;
	align-self: end;
	width: var(--rowww-avatar);
	margin: 0;
}

:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-image img {
	display: block;
	width: var(--rowww-avatar) !important; /* Beats the saved 64 px size. */
	height: var(--rowww-avatar) !important;
	box-shadow: 0 0 0 1px var(--wp--custom--line--subtle);
}

:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-image::after {
	content: "";
	position: absolute;
	inset-block-end: 0;
	inset-inline-end: 0;
	width: 0.625rem;
	height: 0.625rem;
	border: 2px solid var(--wp--preset--color--base);
	border-radius: 50%;
	background: var(--wp--custom--feedback--success);
}

/* Name · title, one quiet line above the bubble. */
:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-group > p {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm) !important; /* Beats the preset class. */
	line-height: 1.4;
}

:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-group > p:first-child {
	grid-area: name;
}

:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-group > p:nth-child(2) {
	grid-area: title;
	padding-inline-start: 0.5em;
}

:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-group:not(.rowww-bubble) > .wp-block-group > p:nth-child(2)::before {
	content: "·";
	margin-inline-end: 0.5em;
}

/* The bubble: a hairline glass panel with a faint accent tint. */
.rowww-personal-cta > p,
.rowww-faq-cta.is-style-card > p,
.rowww-bubble {
	grid-area: bubble;
	justify-self: start;
	max-width: 40rem;
	margin: 0 !important; /* Beats the pattern's margins and flex size. */
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
	border: 1px solid var(--wp--custom--line--subtle);
	border-radius: var(--wp--preset--border-radius--card) var(--wp--preset--border-radius--card) var(--wp--preset--border-radius--card) var(--rowww-bubble-corner);
	background:
		linear-gradient(160deg, color-mix(in srgb, var(--rowww-accent-start) 12%, transparent), transparent 55%),
		color-mix(in srgb, var(--wp--preset--color--contrast) 5%, transparent);
	box-shadow: inset 0 1px 0 color-mix(in srgb, var(--wp--preset--color--contrast) 6%, transparent);
	line-height: 1.55;
	text-wrap: pretty;
}

.rowww-faq-cta.is-style-card > p {
	padding: var(--wp--preset--spacing--40);
	font-style: normal !important; /* The message is not a quote. */
}

/*
 * Every message reads like a chat message: one plain body size and colour,
 * whatever preset the saved block carries. A heading in a longer message is
 * just its first sentence (no heading size, weight or italic).
 */
.rowww-personal-cta > p,
.rowww-faq-cta.is-style-card > p,
.rowww-bubble > :is(p, .wp-block-heading) {
	/* No !important on the colour: the arrival animation hides the text with it. */
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--body) !important;
	font-size: var(--wp--preset--font-size--base) !important;
	font-style: normal !important;
	font-weight: 400 !important;
	letter-spacing: normal;
	line-height: 1.55;
	text-wrap: pretty;
}

.rowww-bubble > * + * {
	margin-block-start: 0.75em !important; /* Paragraph rhythm, not the section gap. */
}

.rowww-bubble > :first-child {
	margin-block-start: 0 !important;
}

.rowww-bubble > :last-child {
	margin-block-end: 0 !important;
}

/* The reply: the button under the bubble. */
:is(.rowww-personal-cta, .rowww-faq-cta.is-style-card) > .wp-block-buttons {
	grid-area: action;
	margin: var(--wp--preset--spacing--20) 0 0 !important; /* Beats the pattern's margin. */
}

/*
 * The message arrives (states from assets/js/message.js): the photo and the
 * name fade in, a small bubble "types" for a moment, then it opens up into the
 * full message and the button follows. The bubble opens with a clip path, so
 * nothing on the page moves.
 */
@media (prefers-reduced-motion: no-preference) {

	.rowww-personal-cta,
	.rowww-faq-cta.is-style-card {
		--rowww-typing: 0.8s; /* When the typing ends and the message opens. */
	}

	:is(.rowww-personal-cta, .rowww-faq-cta).is-pending > :is(p, .rowww-bubble, .wp-block-buttons),
	:is(.rowww-personal-cta, .rowww-faq-cta).is-pending > .wp-block-group:not(.rowww-bubble) > .wp-block-image,
	:is(.rowww-personal-cta, .rowww-faq-cta).is-pending > .wp-block-group:not(.rowww-bubble) > .wp-block-group > p {
		opacity: 0;
	}

	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > .wp-block-group:not(.rowww-bubble) > .wp-block-image,
	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > .wp-block-group:not(.rowww-bubble) > .wp-block-group > p {
		animation: rowww-message-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
	}

	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > .wp-block-buttons {
		animation: rowww-message-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) calc(var(--rowww-typing) + 0.35s) both;
	}

	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > :is(p, .rowww-bubble) {
		animation:
			rowww-message-bubble 0.25s ease-out 0.15s backwards,
			rowww-message-open 0.45s cubic-bezier(0.22, 1, 0.36, 1) var(--rowww-typing) backwards;
	}

	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > .rowww-bubble > * {
		animation: rowww-message-text 0.3s ease-out calc(var(--rowww-typing) + 0.1s) backwards;
	}

	/* A one-paragraph message is the bubble and the text at once: all three
	   animations on it (`:not()` outweighs the bubble rule above). */
	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > p:not(.rowww-bubble) {
		animation:
			rowww-message-bubble 0.25s ease-out 0.15s backwards,
			rowww-message-open 0.45s cubic-bezier(0.22, 1, 0.36, 1) var(--rowww-typing) backwards,
			rowww-message-text 0.3s ease-out calc(var(--rowww-typing) + 0.1s) backwards;
	}

	/* Three typing dots in the small bubble. */
	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > :is(p, .rowww-bubble)::before {
		--rowww-dot: radial-gradient(circle closest-side, var(--wp--preset--color--muted) 95%, transparent);

		content: "";
		position: absolute;
		inset-block-end: 0.9rem;
		inset-inline-start: 1.1rem;
		width: 2rem;
		height: 0.875rem;
		background: var(--rowww-dot), var(--rowww-dot), var(--rowww-dot);
		background-repeat: no-repeat;
		background-size: 0.375rem 0.375rem;
		animation:
			rowww-message-dots 0.5s linear 2,
			rowww-message-dots-out 0.1s linear var(--rowww-typing) forwards;
	}

	:is(.rowww-personal-cta, .rowww-faq-cta).is-arriving > :is(p, .rowww-bubble) {
		position: relative;
	}
}

@keyframes rowww-message-in {

	from {
		opacity: 0;
		transform: translateY(0.375rem);
	}
}

@keyframes rowww-message-bubble {

	from {
		opacity: 0;
		transform: scale(0.85);
		transform-origin: 0 100%;
	}

	to {
		transform-origin: 0 100%;
	}
}

@keyframes rowww-message-open {

	from {
		clip-path: inset(calc(100% - 2.625rem) calc(100% - 4.25rem) 0 0 round 1.3rem 1.3rem 1.3rem var(--rowww-bubble-corner));
	}

	to {
		clip-path: inset(0 round var(--wp--preset--border-radius--card) var(--wp--preset--border-radius--card) var(--wp--preset--border-radius--card) var(--rowww-bubble-corner));
	}
}

@keyframes rowww-message-text {

	from {
		color: transparent;
	}
}

@keyframes rowww-message-dots {

	0%,
	100% {
		background-position: 0 100%, 50% 100%, 100% 100%;
	}

	25% {
		background-position: 0 0, 50% 100%, 100% 100%;
	}

	50% {
		background-position: 0 100%, 50% 0, 100% 100%;
	}

	75% {
		background-position: 0 100%, 50% 100%, 100% 0;
	}
}

@keyframes rowww-message-dots-out {

	to {
		opacity: 0;
		visibility: hidden;
	}
}

/*
 * FAQ sections: on phones the "did not find your question?" text and the
 * contact button move below the questions. The aside column dissolves
 * (`display: contents`) so its two groups can be ordered around the list.
 */
@media (max-width: 781px) {

	.rowww-faq-aside {
		display: contents;
	}

	.rowww-faq-aside > * {
		flex-basis: 100%;
	}

	.rowww-faq-aside > .rowww-faq-cta {
		order: 2;
	}

	.rowww-faq-aside > .rowww-faq-cta > :first-child {
		margin-block-start: 0 !important;
	}
}

/*
 * Ribbon: a slightly tilted, full-width accent band (e.g. an award), class
 * `rowww-ribbon` on a full-width group. Slightly scaled so the tilted band
 * still covers both edges; `main` clips the overflow.
 */
.rowww-ribbon {
	padding-block: var(--wp--preset--spacing--40);
	background: linear-gradient(90deg, var(--rowww-accent-start), var(--rowww-accent-end));
	color: var(--rowww-accent-on);
	rotate: -2deg;
	scale: 1.04;
}

.rowww-ribbon :where(p) {
	font-size: var(--wp--preset--font-size--xl);
	font-weight: 600;
	line-height: 1.2;
}

/*
 * Marquee: a paragraph with `rowww-marquee` scrolls endlessly. The plugin
 * repeats the text in a track (Blocks\Marquee_Render); the track slides by
 * one copy. Copies are separated by a bullet. Static with reduced motion.
 */
.rowww-marquee {
	overflow: hidden;
	white-space: nowrap;
}

.rowww-marquee__track {
	display: flex;
	width: max-content;
}

.rowww-marquee__item::after {
	content: "•";
	padding-inline: 0.6em;
}

/* A link in the line (e.g. to the awarded project) reads as the band text. */
.rowww-marquee a {
	color: inherit;
	text-decoration: none;
}

.rowww-marquee a:focus-visible {
	outline: 2px solid currentcolor;
	outline-offset: 0.15em;
}

@media (prefers-reduced-motion: no-preference) {

	.rowww-marquee__track {
		animation: rowww-marquee-text 30s linear infinite;
	}

	/* Holds still under the pointer or focus, so a link can be clicked. */
	.rowww-marquee:hover .rowww-marquee__track,
	.rowww-marquee:focus-within .rowww-marquee__track {
		animation-play-state: paused;
	}
}

@keyframes rowww-marquee-text {

	to {
		translate: calc(-100% / var(--rowww-copies, 4)) 0;
	}
}

/*
 * Legal pages (imprint, privacy and cookie policy): `rowww-legal` on the
 * content column gives long texts a calm rhythm (anchored h2 sections with a
 * divider, readable line length); `rowww-toc` on a list in the sticky column
 * is the table of contents (links to the h2 anchors).
 */
.rowww-legal {
	max-width: 46rem;
}

.rowww-legal > h2 {
	margin-block-start: var(--wp--preset--spacing--70);
	padding-block-start: var(--wp--preset--spacing--50);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
	font-size: var(--wp--preset--font-size--xl);
}

.rowww-legal > h2:first-child {
	margin-block-start: 0;
	padding-block-start: 0;
	border-block-start: 0;
}

.rowww-legal > h3 {
	margin-block-start: var(--wp--preset--spacing--50);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
}

.rowww-legal :is(p, li) {
	line-height: 1.7;
}

.rowww-legal > .wp-block-group {
	margin-block-start: var(--wp--preset--spacing--40);
}

.rowww-toc {
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: rowww-toc;
}

.rowww-toc li {
	counter-increment: rowww-toc;
}

.rowww-toc a {
	display: flex;
	gap: 0.75em;
	padding-block: 0.35rem;
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	transition: color var(--wp--custom--transition);
}

.rowww-toc a::before {
	content: counter(rowww-toc, decimal-leading-zero);
	flex: none;
	color: var(--rowww-accent-text-start);
	font-variant-numeric: tabular-nums;
}

.rowww-toc a:is(:hover, :focus-visible) {
	color: var(--wp--preset--color--contrast);
}

/*
 * Contact page: the contact person card (accent gradient) next to the
 * inquiry card. Both cards are as tall as the row; the direct contacts sit at
 * the bottom of the person card. On phones the form comes first.
 */
.rowww-contact,
.rowww-thanks {
	padding-block: var(--wp--preset--spacing--50);
}

.rowww-contact__grid > .wp-block-column {
	display: flex;
}

.rowww-contact__grid > .wp-block-column > .wp-block-group {
	flex: 1;
	margin: 0;
}

.rowww-contact__name {
	font-family: var(--wp--preset--font-family--accent);
	line-height: var(--wp--custom--line-height--tight);
}

.rowww-contact__direct {
	margin-block-start: auto !important;
}

.rowww-contact__links,
.rowww-contact__links .wp-block-button {
	width: 100%;
}

.rowww-contact__links .wp-block-button__link {
	display: block;
	width: 100%;
	text-align: start;
}

.rowww-contact__form h1 {
	margin-block-end: var(--wp--preset--spacing--40);
}

.rowww-contact__topic-label {
	margin-block-end: calc(var(--wp--preset--spacing--40) * -0.5);
}

@media (max-width: 781px) {

	.rowww-contact__grid > .wp-block-column:last-child {
		order: -1;
	}

	.rowww-contact__form {
		padding-inline: var(--wp--preset--spacing--40) !important;
	}
}

/*
 * Thank-you page: the mark above the heading sits in a soft accent circle.
 */
.rowww-thanks__intro {
	padding-block-start: var(--wp--preset--spacing--60);
}

.rowww-thanks__mark {
	display: grid !important;
	place-items: center;
	width: 4.5rem;
	height: 4.5rem;
	margin-inline: auto !important;
	border: 1px solid color-mix(in srgb, var(--rowww-accent-start) 60%, transparent);
	border-radius: 50%;
	background: color-mix(in srgb, var(--rowww-accent-start) 15%, transparent);
}

/*
 * Projects overview: two-column grid; the cover zooms in slightly on hover.
 */
.rowww-project-grid .wp-block-post-template {
	row-gap: var(--wp--preset--spacing--70);
}

.rowww-project-grid .wp-block-post-featured-image {
	overflow: hidden;
	border-radius: var(--wp--preset--border-radius--card);
}

.rowww-project-grid .wp-block-post-featured-image img {
	transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: no-preference) {

	.rowww-project-grid .wp-block-post:is(:hover, :focus-within) .wp-block-post-featured-image img {
		transform: scale(1.03);
	}
}

/*
 * Project page (case study): the intro sits below the header; in each
 * chapter the gallery is on the left and the text column on the right stays
 * in view (`rowww-sticky`) while the gallery scrolls past; on phones the
 * gallery comes first, so the images show up before the long text. Gallery
 * images keep their own ratio (projects taken over from elsewhere keep
 * their original images and order) and get the card radius; on desktop
 * they run 1-2-1-2 (one full width, then two side by side), a single image
 * left over at the end is full width too; with `is-pairs-first` the other
 * way round (2-1-2-1).
 */
.rowww-case-intro {
	padding-block-start: var(--wp--preset--spacing--70);
}

.rowww-case-gallery {
	display: grid;
	align-items: start;
	gap: var(--wp--preset--spacing--40);
}

.rowww-case-gallery > .wp-block-image {
	margin: 0;
}

@media (min-width: 782px) {

	.rowww-case-gallery {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.rowww-case-gallery > :nth-child(3n + 1),
	.rowww-case-gallery > :nth-child(3n + 2):last-child {
		grid-column: 1 / -1;
	}

	/* `is-pairs-first`: the gallery opens with a pair (2-1-2-1), e.g. when
	   its first wide image would repeat the cover above. */
	.rowww-case-gallery.is-pairs-first > :nth-child(3n + 1),
	.rowww-case-gallery.is-pairs-first > :nth-child(3n + 2):last-child {
		grid-column: auto;
	}

	.rowww-case-gallery.is-pairs-first > :nth-child(3n),
	.rowww-case-gallery.is-pairs-first > :nth-child(3n + 1):last-child {
		grid-column: 1 / -1;
	}
}

.rowww-case-gallery img {
	width: 100%;
	height: auto;
	border-radius: var(--wp--preset--border-radius--card);
}

/*
 * Case study story (`rowww-case-story` section of `rowww-case-part`
 * columns): the long read around the chapters (starting point, challenge,
 * approach before them; result and the client's words after them). Each part
 * is a row under a hairline: the numbered heading on the left, the text on
 * the right (a lead paragraph, then the muted body). The numbering runs
 * through both story sections of a page (the counter starts at the intro).
 */
.rowww-case-intro {
	counter-reset: rowww-case-part;
}

.rowww-case-part {
	padding-block-start: var(--wp--preset--spacing--50);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
	counter-increment: rowww-case-part;
}

body .rowww-case-story > .rowww-case-part + .rowww-case-part {
	margin-block-start: var(--wp--preset--spacing--60);
}

.rowww-case-part .wp-block-heading {
	font-size: var(--wp--preset--font-size--lg);
}

.rowww-case-part .wp-block-heading::before {
	content: counter(rowww-case-part, decimal-leading-zero);
	display: block;
	margin-block-end: var(--wp--preset--spacing--30);
	color: var(--rowww-accent-text-start);
	font-size: var(--wp--preset--font-size--sm);
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	letter-spacing: 0.08em;
	line-height: 1;
}

.rowww-case-part > .wp-block-column > p {
	max-width: 44rem;
	line-height: 1.7;
	text-wrap: pretty;
}

.rowww-case-part > .wp-block-column > p.is-style-lead {
	line-height: 1.5;
}

/*
 * "More projects": generous space above, then a divider line and a smaller
 * gap to the heading. The extra selector weight beats the layout rule that
 * zeroes the top margin of a group's first child. "More articles" follows a
 * white post body, so it needs neither the line nor the extra margin.
 * Both are hidden when there is nothing else to show.
 */
body .wp-block-group.rowww-more-projects {
	margin-block-start: calc(var(--wp--preset--spacing--80) * 1.25);
	padding-block-start: var(--wp--preset--spacing--70);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
}

/*
 * Section with a divider line above it (`rowww-divided`, e.g. the comparison
 * after the packages on the pricing page): the usual section gap, split in
 * two around a hairline.
 */
body .wp-block-group.rowww-section.rowww-divided {
	margin-block-start: calc(var(--wp--preset--spacing--80) / 2);
	padding-block-start: calc(var(--wp--preset--spacing--80) / 2);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
}

.rowww-more-posts {
	padding-block-start: var(--wp--preset--spacing--80);
}

.rowww-more-projects:not(:has(.wp-block-post)),
.rowww-more-posts:not(:has(.wp-block-post)) {
	display: none;
}

/*
 * Comparison ("without / with"): two cards side by side. The "without" card
 * stays quiet (outline, muted text, cross list), the "with" card carries the
 * accent: outline in the accent, a soft accent light from the top and a
 * checklist. On phones the cards stack, "with" coming second.
 */
.rowww-compare {
	align-items: stretch;
}

.rowww-compare > .wp-block-column {
	display: flex;
}

.rowww-compare > .wp-block-column > .wp-block-group {
	flex: 1;
}

.rowww-compare__without {
	color: var(--wp--preset--color--muted);
}

.rowww-compare__without h3 {
	color: var(--wp--preset--color--muted);
}

.rowww-compare__with {
	position: relative;
	overflow: hidden;
	background-image: radial-gradient(120% 80% at 50% 0%, color-mix(in srgb, var(--rowww-accent-start) 22%, transparent), transparent 70%);
	box-shadow: 0 1.5rem 4rem color-mix(in srgb, var(--rowww-accent-start) 18%, transparent);
}

.rowww-compare__with h3 em {
	font-family: var(--wp--preset--font-family--accent);
	background-image: linear-gradient(90deg, var(--rowww-accent-text-start), var(--rowww-accent-text-end));
	-webkit-background-clip: text;
	background-clip: text;
	color: var(--rowww-accent-text-start);
	-webkit-text-fill-color: transparent;
}

.rowww-compare .wp-block-list > li + li {
	margin-block-start: var(--wp--preset--spacing--30);
	padding-block-start: var(--wp--preset--spacing--30);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
}

/* Markers follow the padding above the divider line. */
.rowww-compare .wp-block-list > li + li::before,
.rowww-compare .wp-block-list > li + li::after {
	inset-block-start: calc(var(--wp--preset--spacing--30) + (1lh - 1.25rem) / 2);
}

/*
 * Audience ("who is it for"): text on the left, a 2×2 grid of situations on
 * the right; each card has an icon and a short title.
 */
.rowww-audience .wp-block-rowww-icon {
	margin-block-end: var(--wp--preset--spacing--30);
}

/*
 * AI Assist "what you get" cards (`rowww-pillar`): frosted glass panels, the
 * same as "Card (accent)" (core-group.css: tint, edge, light, hover, icon
 * tile). Upright: from 782px each card is taller than wide; the checklist
 * sits at the bottom under a thin rule, so the three lists line up.
 */
.rowww-pillar {
	display: flex;
	flex-direction: column;

	/* Compact (1.5rem on every side, every screen): the text is long enough. */
	padding: calc(var(--wp--preset--spacing--40) + var(--wp--preset--spacing--10) / 2);
	border-radius: var(--wp--preset--border-radius--card);
}

.rowww-pillar > .wp-block-list {
	margin-block: auto 0;
	padding-block-start: var(--wp--preset--spacing--40);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
}

/* Breathing room between the text and the rule, kept when the card grows. */
.rowww-pillar > p:last-of-type {
	margin-block-end: var(--wp--preset--spacing--50);
}

/*
 * The service link under the text (`rowww-pillar__link`): accent text with an
 * arrow; it stretches over the card (its ::before), so the whole card is the
 * link, like the AI overview cards.
 */
.rowww-pillar {
	cursor: pointer;
}

.rowww-pillar__link a {
	color: var(--rowww-accent-text-start);
	font-weight: 600;
	text-decoration: none;
}

.rowww-pillar__link a::after {
	content: " →";
}

.rowww-pillar__link a::before {
	content: "";
	position: absolute;
	z-index: 1;
	inset: 0;
	border-radius: inherit;
}

.rowww-pillar__link a:is(:hover, :focus-visible) {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.rowww-pillar:has(.rowww-pillar__link a:focus-visible) {
	outline: 2px solid var(--rowww-accent-text-start);
	outline-offset: 2px;
}

.rowww-pillar__link a:focus-visible {
	outline: none;
}

@media (min-width: 782px) {

	/*
	 * 4:5 as the minimum: a longer text makes the card taller instead of
	 * clipping the checklist. `overflow: hidden` (from the card style) makes
	 * a scroll container, which drops the aspect-ratio's automatic
	 * content-based minimum height; `clip` cuts the light the same way
	 * without that. A grid item with an aspect ratio is not stretched by
	 * default, so a card that grows would leave its neighbours shorter:
	 * `align-self: stretch` keeps the row even, and `width: 100%` stops the
	 * stretched height from widening the card through the ratio.
	 */
	.wp-block-group.rowww-pillar {
		align-self: stretch;
		width: 100%;
		aspect-ratio: 4 / 5;
		overflow: clip;
	}
}

/*
 * AI Assist sample requests (`rowww-request`): chat bubbles (the "tail"
 * corner bottom right, like the visitor's message), each with the result it
 * leads to as an accent pill. They rise in one after the other as they
 * scroll into view (motion only).
 */
.rowww-request {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
	justify-content: space-between;
	padding: var(--wp--preset--spacing--40);
	border: 1px solid var(--wp--custom--line--subtle);
	border-radius: 1.25rem 1.25rem 0.35rem 1.25rem;
	background: color-mix(in srgb, var(--wp--preset--color--contrast) 7%, transparent);
	transition:
		translate 400ms cubic-bezier(0.22, 1, 0.36, 1),
		border-color 300ms ease,
		background-color 300ms ease;
}

.rowww-request > * {
	margin-block: 0;
}

.rowww-request:hover {
	border-color: color-mix(in srgb, var(--rowww-accent-start) 70%, transparent);
	background-color: color-mix(in srgb, var(--rowww-accent-start) 10%, transparent);
	translate: 0 -4px;
}

.rowww-request__result {
	align-self: flex-start;
	padding: 0.2rem 0.7rem 0.2rem 0.55rem;
	border-radius: 999px;
	background: linear-gradient(135deg, var(--rowww-accent-start), var(--rowww-accent-end));
	color: var(--rowww-accent-on);
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 600;
}

.rowww-request__result::before {
	content: "✓ ";
}

@supports (animation-timeline: view()) {

	@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {

		.rowww-request {
			animation: rowww-request-in linear both;
			animation-timeline: view();
			animation-range: entry 0% entry 70%;
		}

		.rowww-request:nth-child(even) {
			animation-range: entry 10% entry 80%;
		}
	}
}

@keyframes rowww-request-in {

	from {
		opacity: 0;
		transform: translateY(1.5rem) scale(0.96);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/* Two in a row on phones, so tighter. */
@media (max-width: 599px) {

	.rowww-request {
		padding: var(--wp--preset--spacing--30);
		font-size: var(--wp--preset--font-size--sm);
	}
}

/*
 * Front page work section head (`rowww-works`): a large display heading
 * with tight leading on the left, text and link on the right, a thin rule
 * underneath before the case studies.
 */
.rowww-works__head {
	padding-block-end: var(--wp--preset--spacing--60);
	border-block-end: 1px solid var(--wp--custom--line--subtle);
}

/* Large display heading (xxxl), also usable elsewhere: `rowww-display`. */
.rowww-works__title,
.rowww-display {
	margin-block-start: var(--wp--preset--spacing--30);
	line-height: 1;
	letter-spacing: -0.03em;
	text-wrap: balance;
}

/*
 * Phones: the size follows the screen width, so the accent line of a display
 * heading ("speaks for itself.", "for your visitors.") fits on one line down
 * to 320px.
 */
@media (max-width: 781px) {

	.rowww-works__title,
	.rowww-display {
		font-size: min(var(--wp--preset--font-size--xxxl), calc((100vw - 2 * var(--wp--custom--gutter)) / 9.4)) !important;
	}
}

/* The accent words stay on one line where there is room. */
@media (min-width: 782px) {

	.rowww-works__title em,
	.rowww-display em {
		white-space: nowrap;
	}
}

/*
 * The chat demo right under the hero tucks up into the hero's bottom padding
 * (on wider screens, where that padding is large), so there is less room
 * above it than below.
 */
.wp-block-rowww-hero + .wp-block-rowww-chat-demo {
	position: relative;
	margin-block-start: 0;
}

@media (min-width: 782px) {

	.wp-block-rowww-hero + .wp-block-rowww-chat-demo {
		margin-block-start: calc(-1 * var(--wp--preset--spacing--70));
	}
}

/*
 * Closing row of a work section (`rowww-teaser-row`): a thin line above, the
 * text on the left and the button on the right (stacked on mobile). The
 * opening words ("This is just a taste.") are large accent type on their own
 * line; the rest of the sentence is plain, muted and smaller (`base`).
 */
.rowww-teaser-row {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--40);
	margin-block-start: var(--wp--preset--spacing--70);
	padding-block-start: var(--wp--preset--spacing--60);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
}

.rowww-teaser-row > * {
	margin-block: 0;
}

.rowww-teaser-row > .wp-block-buttons {
	flex-shrink: 0;
}

@media (min-width: 782px) {

	.rowww-teaser-row {
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
		gap: var(--wp--preset--spacing--60);
	}
}

/* Tight leading: the line box follows the paragraph's larger size (`md`),
   so the smaller muted text gets ~1.6 spacing instead of 2. */
.rowww-teaser {
	line-height: var(--wp--custom--line-height--tight);
}

.rowww-teaser strong {
	display: block;
	margin-block-end: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--xl);
	font-weight: inherit;
	line-height: 1.2;
}

.rowww-teaser > em {
	font-family: inherit;
	font-size: var(--wp--preset--font-size--base);
	font-style: normal;
	color: var(--wp--preset--color--muted);
	background: none;
	-webkit-text-fill-color: currentcolor;
}

/*
 * The personal call to action right after a work section is set well apart
 * from it. The card's own inline top margin (from the pattern) has to be
 * overridden here.
 */
.rowww-section:has(.wp-block-rowww-featured-projects) + .rowww-personal-cta {
	margin-block-start: calc(var(--wp--preset--spacing--80) * 1.25) !important;
}

.single-rowww_service .rowww-section:has(.wp-block-rowww-featured-projects) + .rowww-personal-cta {
	margin-block-start: var(--wp--preset--spacing--80) !important;
}

/*
 * Light section (e.g. the body of a blog post): the colour presets switch to
 * the light set (`custom.light`) inside it, so every block below reads dark
 * text on white without its own light variant. The accent text colour uses
 * the accent surface tone, which is the readable one on white.
 */
.rowww-light {
	--wp--preset--color--base: var(--wp--custom--light--surface);
	--wp--preset--color--contrast: var(--wp--custom--light--text);
	--wp--preset--color--muted: var(--wp--custom--light--muted);
	--wp--preset--color--surface: var(--wp--custom--light--surface-alt);
	--wp--custom--line--subtle: color-mix(in srgb, var(--wp--custom--light--text) 8%, transparent);
	--wp--custom--line--default: color-mix(in srgb, var(--wp--custom--light--text) 16%, transparent);
	--wp--custom--line--strong: color-mix(in srgb, var(--wp--custom--light--text) 40%, transparent);
	--rowww-accent-text-start: var(--rowww-accent-start);
	--rowww-accent-text-end: var(--rowww-accent-start);

	background-color: var(--wp--custom--light--surface);
	color: var(--wp--custom--light--text);
}

/* Link hover: the lime call-to-action colour is unreadable on white. */
.rowww-light a:where(:not(.wp-element-button)):hover {
	color: var(--rowww-accent-start);
}

/*
 * Blog: post cards (image, category tags on the image, date and reading
 * time, title, short excerpt) and the topic pills in the sidebar.
 */
.rowww-post-card {
	position: relative;
}

.rowww-post-card .wp-block-post-featured-image {
	overflow: hidden;
	margin: 0;
	border-radius: var(--wp--preset--border-radius--card);
}

.rowww-post-card .wp-block-post-featured-image img {
	transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: no-preference) {

	.rowww-post-card:is(:hover, :focus-within) .wp-block-post-featured-image img {
		transform: scale(1.03);
	}
}

.rowww-post-card > .rowww-card-cats {
	position: absolute;
	inset-block-start: var(--wp--preset--spacing--30);
	inset-inline-start: var(--wp--preset--spacing--30);
	margin: 0;
}

.rowww-card-cats {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--10);
}

.rowww-card-cats .wp-block-post-terms__separator {
	display: none;
}

.rowww-card-cats a {
	padding: 0.3rem 0.8rem;
	border-radius: var(--wp--preset--border-radius--pill);
	background: color-mix(in srgb, var(--wp--preset--color--base) 70%, transparent);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--xs);
	text-decoration: none;
	-webkit-backdrop-filter: blur(8px);
	backdrop-filter: blur(8px);
}

/* On the card image the pill is filled (white on the dark site, dark in a
   light scope), so it stands out on any photo. */
.rowww-post-card > .rowww-card-cats a {
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	font-weight: 500;
	box-shadow: 0 2px 8px color-mix(in srgb, var(--wp--preset--color--base) 35%, transparent);
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
}

/* In the post header the pill sits on the dark page, not on a photo: it gets
   a visible outline instead of the frosted fill. */
.rowww-post-hero .rowww-card-cats a {
	border: 1px solid var(--wp--custom--line--default);
	background: var(--wp--preset--color--surface);
	transition: border-color var(--wp--custom--transition);
}

.rowww-post-hero .rowww-card-cats a:is(:hover, :focus-visible) {
	border-color: var(--rowww-accent-start);
}

.rowww-post-meta {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--sm);
}

.rowww-post-meta > * + *::before {
	content: "·";
	margin-inline-end: 0.5em;
}

.rowww-post-card .wp-block-post-title a {
	text-decoration: none;
}

/* The sidebar CTA only on wide screens: on phones it would push the H1 down
   (the CTA banner closes the page anyway). */
@media (max-width: 781px) {

	.rowww-blog-cta,
	.wp-block-buttons.rowww-blog-cta {
		display: none;
	}
}

/* Topic pills: "All" plus the post categories (core/categories). */
.rowww-topics,
.rowww-topics .wp-block-categories {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
	padding: 0;
	list-style: none;
}

.rowww-topics a {
	display: block;
	padding: 0.5rem 1rem;
	border: 1px solid var(--wp--custom--line--default);
	border-radius: var(--wp--preset--border-radius--pill);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--sm);
	text-decoration: none;
	transition: border-color var(--wp--custom--transition), background-color var(--wp--custom--transition);
}

.rowww-topics a:is(:hover, :focus-visible) {
	border-color: var(--rowww-accent-start);
}

/* The current topic is filled ("All" on the blog page, else the category). */
.blog .rowww-topics__all a,
.rowww-topics .current-cat > a {
	border-color: transparent;
	background: linear-gradient(135deg, var(--rowww-accent-start), var(--rowww-accent-end));
	color: var(--rowww-accent-on);
}

/*
 * Blog post: dark hero, then the white body with the text on the left and
 * the sticky table of contents, AI summary and contact card on the right.
 */
.rowww-post-hero {
	padding-block: var(--wp--preset--spacing--70);
}

.rowww-post-body {
	padding-block: var(--wp--preset--spacing--70) var(--wp--preset--spacing--80);
}

.rowww-post-body .wp-block-post-content > * + h2 {
	margin-block-start: var(--wp--preset--spacing--70);
}

.rowww-post-body .wp-block-post-content :is(p, li) {
	font-size: var(--wp--preset--font-size--md);
	line-height: 1.7;
}

.rowww-post-body .wp-block-post-content a {
	color: var(--rowww-accent-start);
	text-underline-offset: 0.2em;
}

/* Images in the article: card corners and a quiet caption. */
.rowww-post-body .wp-block-post-content .wp-block-image {
	margin-block: var(--wp--preset--spacing--60);
}

.rowww-post-body .wp-block-post-content .wp-block-image img {
	border-radius: var(--wp--preset--border-radius--card);
}

.rowww-post-body .wp-block-post-content .wp-element-caption {
	margin-block-start: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--sm);
	text-align: start;
}

.rowww-post-aside > * + * {
	margin-block-start: var(--wp--preset--spacing--30);
}

/* Author box under the post: photo with an accent ring, name, title, bio and
   a link to the About page; a soft accent glow from the top left corner. */
.rowww-post-author {
	position: relative;
	overflow: hidden;
	background:
		radial-gradient(circle at 0 0, color-mix(in srgb, var(--rowww-accent-start) 14%, transparent), transparent 55%),
		var(--wp--preset--color--surface);
}

.rowww-post-author__photo {
	flex-shrink: 0;
	margin: 0;
}

.rowww-post-author__photo img {
	border: 2px solid var(--wp--preset--color--base);
	box-shadow: 0 0 0 2px var(--rowww-accent-start);
}

.rowww-post-author__name {
	margin-block-start: var(--wp--preset--spacing--10);
	font-family: var(--wp--preset--font-family--accent);
}

.rowww-post-author__bio {
	max-width: 40em;
	margin-block-start: var(--wp--preset--spacing--30);
}

.rowww-post-author .wp-block-buttons {
	column-gap: var(--wp--preset--spacing--50);
}

@media (max-width: 599px) {

	.rowww-post-author {
		flex-direction: column;
	}
}

/*
 * Visitor AI chat sample (`rowww-visitor-chat` group, section-ai-chat): a
 * chat panel with a header, visitor questions on the right, the assistant's
 * answers on the left with a link pill, and a small note. In view the
 * conversation plays like the AI Assist demo (see below, visitor-chat.js).
 */
.rowww-visitor-chat {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
	max-width: 30rem;
	margin-inline: auto;
	padding: var(--wp--preset--spacing--40);
	border: 1px solid var(--wp--custom--line--subtle);
	border-radius: var(--wp--preset--border-radius--card);
	background: var(--wp--preset--color--surface);
	box-shadow: 0 2rem 4rem rgb(0 0 0 / 0.35);
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1.5;
}

.rowww-visitor-chat > * {
	margin-block: 0;
}

.rowww-visitor-chat__head {
	display: flex;
	gap: 0.5rem;
	align-items: center;
	padding-block-end: var(--wp--preset--spacing--30);
	border-block-end: 1px solid var(--wp--custom--line--subtle);
	color: var(--wp--preset--color--muted);
}

.rowww-visitor-chat__head::before {
	content: "";
	width: 0.6rem;
	height: 0.6rem;
	border-radius: 50%;
	background: linear-gradient(135deg, var(--rowww-accent-start), var(--rowww-accent-end));
	box-shadow: 0 0 0.75rem var(--rowww-accent-start);
}

.rowww-visitor-chat__head strong {
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
}

.rowww-visitor-chat__msg {
	max-width: 88%;
	padding: 0.75rem 1rem;
	border-radius: 1rem 1rem 1rem 0.3rem;
	background: linear-gradient(135deg, var(--rowww-accent-start), var(--rowww-accent-end));
	color: var(--rowww-accent-on);
}

.rowww-visitor-chat__msg.is-user {
	align-self: flex-end;
	border-radius: 1rem 1rem 0.3rem 1rem;
	background: color-mix(in srgb, var(--wp--preset--color--contrast) 10%, transparent);
	color: var(--wp--preset--color--contrast);
}

.rowww-visitor-chat__link {
	display: inline-block;
	margin-block-start: 0.5rem;
	padding: 0.2rem 0.75rem;
	border-radius: 999px;
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 600;
}

.rowww-visitor-chat__link::after {
	content: " →";
}

.rowww-visitor-chat__note {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--xs);
	text-align: center;
}

/* Typing dots and replay button: added by visitor-chat.js, only animated. */
.rowww-visitor-chat__typing {
	display: none;
	gap: 0.3rem;
	align-self: flex-start;
	overflow: hidden;
	padding: 0.8rem 1rem;
	border-radius: 1rem 1rem 1rem 0.3rem;
	background: color-mix(in srgb, var(--wp--preset--color--contrast) 10%, transparent);
}

.rowww-visitor-chat__typing span {
	width: 0.4rem;
	height: 0.4rem;
	border-radius: 50%;
	background: var(--wp--preset--color--muted);
}

.rowww-visitor-chat__replay {
	padding: 0;
	border: 0;
	background: none;
	color: var(--wp--preset--color--contrast);
	font: inherit;
	text-decoration: underline;
	text-underline-offset: 0.2em;
	cursor: pointer;
}

.rowww-visitor-chat__replay:hover,
.rowww-visitor-chat__replay:focus-visible {
	color: var(--rowww-accent-text-start);
}

/*
 * The conversation plays once in view (visitor-chat.js: `is-ready`, then
 * `is-playing`), like the AI Assist chat demo: question from the right,
 * typing dots, the answer from the left, its link pill pops; then the
 * second round. The timing is the animation delays below.
 */
@media (prefers-reduced-motion: no-preference) {

	.rowww-visitor-chat.is-ready:not(.is-playing) :is(.rowww-visitor-chat__msg, .rowww-visitor-chat__note) {
		opacity: 0;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__typing {
		display: flex;
		animation: rowww-visitor-typing 1300ms ease 900ms both;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__typing span {
		animation: rowww-visitor-dot 900ms ease-in-out infinite;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__typing span:nth-child(2) {
		animation-delay: 150ms;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__typing span:nth-child(3) {
		animation-delay: 300ms;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__msg.is-user {
		animation: rowww-visitor-from-right 600ms cubic-bezier(0.22, 1, 0.36, 1) 300ms both;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__msg:not(.is-user) {
		animation: rowww-visitor-from-left 650ms cubic-bezier(0.22, 1, 0.36, 1) 2200ms both;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__link {
		animation: rowww-visitor-pop 420ms cubic-bezier(0.34, 1.56, 0.64, 1) 2800ms both;
	}

	/* Second round: the elements after the first answer. */
	.rowww-visitor-chat.is-playing .rowww-visitor-chat__msg:not(.is-user) ~ .rowww-visitor-chat__msg.is-user {
		animation-delay: 4000ms;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__msg:not(.is-user) ~ .rowww-visitor-chat__typing {
		animation-delay: 4600ms;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__msg:not(.is-user) ~ .rowww-visitor-chat__msg:not(.is-user) {
		animation-delay: 5900ms;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__msg:not(.is-user) ~ .rowww-visitor-chat__msg:not(.is-user) .rowww-visitor-chat__link {
		animation-delay: 6500ms;
	}

	.rowww-visitor-chat.is-playing .rowww-visitor-chat__note {
		animation: rowww-visitor-in 500ms ease 7000ms both;
	}
}

@keyframes rowww-visitor-from-right {

	from {
		opacity: 0;
		transform: translateX(2.5rem) scale(0.92);
	}
}

@keyframes rowww-visitor-from-left {

	from {
		opacity: 0;
		transform: translateX(-2.5rem) scale(0.92);
	}
}

@keyframes rowww-visitor-pop {

	from {
		opacity: 0;
		transform: scale(0.6);
	}
}

@keyframes rowww-visitor-in {

	from {
		opacity: 0;
		transform: translateY(0.5rem);
	}
}

/* Shows, stays, and makes room for the answer. */
@keyframes rowww-visitor-typing {

	/* While waiting and when gone it takes no room (the gap is cancelled). */
	0% {
		max-height: 0;
		margin-block-end: calc(-1 * var(--wp--preset--spacing--30));
		padding-block: 0;
		opacity: 0;
	}

	12%,
	88% {
		max-height: 3rem;
		padding-block: 0.8rem;
		opacity: 1;
	}

	100% {
		max-height: 0;
		margin-block-end: calc(-1 * var(--wp--preset--spacing--30));
		padding-block: 0;
		opacity: 0;
	}
}

@keyframes rowww-visitor-dot {

	0%,
	60%,
	100% {
		opacity: 0.35;
		transform: none;
	}

	30% {
		opacity: 1;
		transform: translateY(-0.2rem);
	}
}

/* "Open the AI Chat" buttons only while the chat is on the page. */
body:not(.has-rowww-ai-chat) .rowww-ai-chat-trigger {
	display: none;
}

/* "Cookie settings" links (footer, legal bar) only while there is a cookie
   banner, i.e. a measurement tag to consent to (rowww-core Privacy\Consent). */
body:not(.has-rowww-consent) .rowww-consent-trigger {
	display: none;
}

/*
 * AI overview cards (section-ai-overview): AI Assist in the default accent,
 * the visitor AI Chat in accent 2; the last line links down to the section.
 */

/* Same feel as the service category cards: accent tint; on hover the card
 * lifts, an accent light pours in from the top and the illustration grows a
 * little. */
.rowww-ai-overview__card.rowww-ai-overview__card {
	--rowww-card-ease: cubic-bezier(0.22, 1, 0.36, 1);

	position: relative;
	isolation: isolate;
	overflow: hidden;
	height: 100%;
	background-color: color-mix(in srgb, var(--rowww-accent-start) 10%, transparent);
	transition:
		transform 500ms var(--rowww-card-ease),
		border-color 400ms ease,
		background-color 400ms ease,
		box-shadow 500ms var(--rowww-card-ease);
}

.rowww-ai-overview__card::before {
	content: "";
	position: absolute;
	z-index: -1;
	inset: -40% -20% auto;
	height: 80%;
	background: radial-gradient(ellipse at 50% 0%, color-mix(in srgb, var(--rowww-accent-end) 45%, transparent), transparent 70%);
	opacity: 0;
	transform: translateY(-20%);
	transition: opacity 500ms ease, transform 600ms var(--rowww-card-ease);
	pointer-events: none;
}

.rowww-ai-overview__card.rowww-ai-overview__card:is(:hover, :focus-within) {
	border-color: var(--rowww-accent-text-start);
	background-color: color-mix(in srgb, var(--rowww-accent-start) 16%, transparent);
	box-shadow: 0 1.5rem 3rem -1.5rem color-mix(in srgb, var(--rowww-accent-start) 70%, transparent);
	transform: translateY(-6px);
}

.rowww-ai-overview__card:is(:hover, :focus-within)::before {
	opacity: 1;
	transform: none;
}

.rowww-ai-overview__visual img {
	transition: transform 600ms var(--rowww-card-ease);
}

.rowww-ai-overview__card:is(:hover, :focus-within) .rowww-ai-overview__visual img {
	transform: scale(1.03);
}

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

	.rowww-ai-overview__card.rowww-ai-overview__card,
	.rowww-ai-overview__card::before,
	.rowww-ai-overview__visual img {
		transition: none;
	}

	.rowww-ai-overview__card.rowww-ai-overview__card:is(:hover, :focus-within),
	.rowww-ai-overview__card:is(:hover, :focus-within) .rowww-ai-overview__visual img {
		transform: none;
	}
}

/*
 * AI overview entrance, tied to the scroll: while the section comes up, the
 * eyebrow, the heading's first line, its accent line and the intro rise into
 * place one after the other, then the two cards follow, the second a little
 * later. The keyframes ease out, so each part
 * settles softly even though the scroll drives it. The columns move, not the
 * cards, so the cards' own hover lift keeps working. Frontend only, from
 * 782px, without reduced motion; elsewhere everything is in place.
 */
@supports (animation-timeline: view()) {

	@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {

		body:not(.editor-styles-wrapper) .rowww-ai-overview {
			view-timeline: --rowww-ai-head block;
		}

		body:not(.editor-styles-wrapper) .rowww-ai-overview > .rowww-compare {
			view-timeline: --rowww-ai-cards block;
		}

		body:not(.editor-styles-wrapper) .rowww-ai-overview > :is(.is-style-eyebrow, .rowww-display, .rowww-measure),
		body:not(.editor-styles-wrapper) .rowww-ai-overview > .rowww-display em {
			animation: rowww-ai-rise linear both;
			animation-timeline: --rowww-ai-head;
			animation-range: entry 8% entry 58%;
		}

		body:not(.editor-styles-wrapper) .rowww-ai-overview > .rowww-display {
			animation-range: entry 14% entry 66%;
		}

		/* The accent line follows the first one. */
		body:not(.editor-styles-wrapper) .rowww-ai-overview > .rowww-display em {
			display: inline-block;

			/* The gradient text is painted only inside the box: room for the
			 * descenders (g, y), taken back so the line height stays. */
			padding-block-end: 0.2em;
			margin-block-end: -0.2em;
			animation-range: entry 22% entry 74%;
		}

		body:not(.editor-styles-wrapper) .rowww-ai-overview > .rowww-measure {
			animation-range: entry 28% entry 80%;
		}

		body:not(.editor-styles-wrapper) .rowww-ai-overview > .rowww-compare > .wp-block-column {
			will-change: transform, opacity;
			animation: rowww-ai-card-in linear both;
			animation-timeline: --rowww-ai-cards;
			animation-range: entry 0% cover 35%;
		}

		body:not(.editor-styles-wrapper) .rowww-ai-overview > .rowww-compare > .wp-block-column + .wp-block-column {
			animation-range: entry 12% cover 45%;
		}

		/* Smooth scrolling: no live blur under the moving, fading cards (it
		 * would be recomputed on every frame); the illustration still fades
		 * out through its mask. */
		body:not(.editor-styles-wrapper) .rowww-ai-overview__visual::after {
			display: none;
		}
	}
}

@keyframes rowww-ai-rise {

	from {
		opacity: 0;
		transform: translateY(4.5rem);
		animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes rowww-ai-card-in {

	from {
		opacity: 0;
		transform: translateY(10rem);
		animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/*
 * Card illustration window (the AI overview cards and the four maintenance
 * risk cards): only the top left part of a larger UI sketch shows, drawn
 * larger than the frame and cut off by the card's right edge, and the bottom
 * fades out (and, from 782px, blurs progressively) into the text below.
 * The risk card classes are on images saved in page content, so they are
 * listed here rather than replaced by one shared class.
 * Per card type: `--rowww-visual-pad` (the card's right padding, which the
 * window runs out over), `--rowww-visual-ratio`, `--rowww-visual-scale`
 * (the sketch's width against the window) and `--rowww-visual-fade` (where
 * the fade starts).
 */
:is(.rowww-ai-overview__visual, .rowww-risk-card-down, .rowww-risk-card-slow, .rowww-risk-card-backup, .rowww-risk-card-expiry) {
	--rowww-visual-pad: var(--wp--preset--spacing--60);

	position: relative;
	overflow: hidden;
	aspect-ratio: var(--rowww-visual-ratio, 16 / 10);
	margin: 0 calc(var(--rowww-visual-pad) * -1) var(--wp--preset--spacing--30) 0;
	-webkit-mask-image: linear-gradient(to bottom, #000 var(--rowww-visual-fade, 62%), transparent 100%);
	mask-image: linear-gradient(to bottom, #000 var(--rowww-visual-fade, 62%), transparent 100%);
}

/* The risk cards (Card (accent)) are narrower and padded with spacing 40,
 * and their sketches carry key figures at the right and lower down, so the
 * sketch is barely enlarged (only its frame runs out over the edge), the
 * window is taller and the fade starts later. */
:is(.rowww-risk-card-down, .rowww-risk-card-slow, .rowww-risk-card-backup, .rowww-risk-card-expiry) {
	--rowww-visual-pad: var(--wp--preset--spacing--40);
	--rowww-visual-ratio: 16 / 11;
	--rowww-visual-scale: 102%;
	--rowww-visual-fade: 66%;

	margin-bottom: 0;
}

:is(.rowww-ai-overview__visual, .rowww-risk-card-down, .rowww-risk-card-slow, .rowww-risk-card-backup, .rowww-risk-card-expiry) img {
	display: block;
	width: var(--rowww-visual-scale, 112%);
	max-width: none;
	height: auto;
	margin: 4% 0 0 4%;
	transform-origin: top left;
}

@media (min-width: 782px) {

	:is(.rowww-ai-overview__visual, .rowww-risk-card-down, .rowww-risk-card-slow, .rowww-risk-card-backup, .rowww-risk-card-expiry)::after {
		content: "";
		position: absolute;
		inset: auto 0 0;
		height: 32%;
		-webkit-backdrop-filter: blur(6px);
		backdrop-filter: blur(10px);
		-webkit-mask-image: linear-gradient(to bottom, transparent, #000 75%);
		mask-image: linear-gradient(to bottom, transparent, #000 75%);
		pointer-events: none;
	}
}

/* The risk card sketch grows a little as the card lifts (as in the AI
 * overview cards). */
@media (prefers-reduced-motion: no-preference) {

	:is(.rowww-risk-card-down, .rowww-risk-card-slow, .rowww-risk-card-backup, .rowww-risk-card-expiry) img {
		transition: transform 600ms var(--rowww-card-ease);
	}

	.is-style-card-accent:is(:hover, :focus-within) > :is(.rowww-risk-card-down, .rowww-risk-card-slow, .rowww-risk-card-backup, .rowww-risk-card-expiry) img {
		transform: scale(1.03);
	}
}

.rowww-ai-overview__link a {
	color: var(--rowww-accent-text-start);
	font-weight: 600;
	text-decoration: none;
}

.rowww-ai-overview__link a::after {
	content: " ↓";
}

/* Linking to another page (e.g. from the home page): an arrow forward. */
.rowww-ai-overview__link a:not([href^="#"])::after {
	content: " →";
}

.rowww-ai-overview__link a:is(:hover, :focus-visible) {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/*
 * Feature panel (`rowww-feature-panel` on a "Card (accent)" section, e.g. the
 * maintenance promo on the home page): the glass card at section size. It
 * does not lift on hover (too large to move); its light still drifts.
 */
.wp-block-group.is-style-card-accent.rowww-feature-panel:is(:hover, :focus-within) {
	transform: none;
}

/*
 * Stat grid (`rowww-stat-grid` on a columns block, e.g. the three numbers
 * of section-about): one hairline-framed panel split into cells by hairline
 * dividers and a faint tint fading down. Stacked on phones, divided by
 * horizontal lines.
 */
.wp-block-columns.rowww-stat-grid {
	overflow: hidden;
	border: 1px solid var(--wp--custom--line--subtle);
	border-radius: var(--wp--preset--border-radius--card);
	background: linear-gradient(180deg, color-mix(in srgb, var(--wp--preset--color--contrast) 3%, transparent), transparent 70%);
}

.rowww-stat-grid > .wp-block-column {
	padding: var(--wp--preset--spacing--60);
}

.rowww-stat-grid > .wp-block-column + .wp-block-column {
	border-inline-start: 1px solid var(--wp--custom--line--subtle);
}

/*
 * Phones: a compact stat grid (number and title only, the description is
 * left out), so the section is shorter.
 */
@media (max-width: 781px) {

	.rowww-stat-grid > .wp-block-column + .wp-block-column {
		border-inline-start: 0;
		border-block-start: 1px solid var(--wp--custom--line--subtle);
	}

	.rowww-stat-grid > .wp-block-column {
		padding: var(--wp--preset--spacing--50);
	}

	.rowww-stat-grid > .wp-block-column > .wp-block-heading {
		margin-block-start: var(--wp--preset--spacing--30) !important;
	}

	.rowww-stat-grid > .wp-block-column > p:not(.is-style-stat) {
		display: none;
	}
}

/*
 * Tile grid (`rowww-tile-grid` on a grid group of small icon cards, e.g. the
 * maintenance services): on phones two cards stand in a row instead of one
 * long column, a little tighter and in smaller type. A card spanning two
 * columns (the contact cell) keeps the whole row.
 */
@media (max-width: 600px) {

	.wp-block-group.rowww-tile-grid.is-layout-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--wp--preset--spacing--20);
	}

	.rowww-tile-grid > .wp-block-group.wp-block-group {
		padding: var(--wp--preset--spacing--30);
	}

	.rowww-tile-grid > .wp-block-group > h3.wp-block-heading {
		margin-top: var(--wp--preset--spacing--30) !important;
		font-size: var(--wp--preset--font-size--base) !important;
		line-height: var(--wp--custom--line-height--tight);
		overflow-wrap: break-word;
	}

	.rowww-tile-grid > .wp-block-group > p {
		font-size: var(--wp--preset--font-size--sm);
	}
}

/*
 * The AI overview cards are links as a whole: the card's link stretches
 * over the card (its ::before). When the link opens a details dialog
 * (`aria-haspopup`, set by details-dialog.js) it ends in a round "+".
 */
.rowww-ai-overview__card {
	cursor: pointer;
}

.rowww-ai-overview__link a::before {
	content: "";
	position: absolute;
	z-index: 1;
	inset: 0;
	border-radius: inherit;
}

.rowww-ai-overview__link a[aria-haspopup]::after {
	content: "+";
	display: inline-grid;
	place-items: center;
	width: 1.6em;
	height: 1.6em;
	margin-inline-start: 0.5em;
	border-radius: 50%;
	background: linear-gradient(135deg, var(--rowww-accent-start), var(--rowww-accent-end));
	color: var(--rowww-accent-on);
	font-size: 0.9em;
	line-height: 1;
	vertical-align: middle;
}

/*
 * Details dialog (`rowww-details`, assets/js/details-dialog.js): a heading
 * and a row of slides that scrolls sideways, in a full-screen dialog, with
 * dots and previous / next buttons below. Outside the dialog (without
 * JavaScript) the group only shows while it is the URL fragment; in the
 * editor it is always shown.
 */
:where(body:not(.editor-styles-wrapper)) .rowww-details:not(:target, .is-in-dialog) {
	display: none;
}

.rowww-details {
	/* Where the heading and the first slide start: the wide content edge. */
	--rowww-details-inset: max(var(--wp--custom--gutter), (100% - var(--wp--style--global--wide-size, 1250px)) / 2);
	--rowww-details-tone: color-mix(in srgb, var(--wp--preset--color--contrast) 6%, var(--wp--preset--color--base));
}

html:has(.rowww-details-dialog[open]) {
	overflow: hidden;
}

.rowww-details-dialog {
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	width: 100%;
	max-width: none;
	height: 100%;
	max-height: none;
	margin: 0;
	padding: var(--wp--preset--spacing--60) 0 var(--wp--preset--spacing--30);
	border: 0;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	overflow-x: hidden;
	overflow-y: auto;
	overscroll-behavior: contain;
}

.rowww-details-dialog:not([open]) {
	display: none;
}

.rowww-details-dialog::backdrop {
	background: var(--wp--preset--color--base);
}

@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {

	.rowww-details-dialog,
	.rowww-details-dialog::backdrop {
		transition:
			opacity 350ms ease,
			transform 500ms cubic-bezier(0.22, 1, 0.36, 1),
			overlay 350ms allow-discrete,
			display 350ms allow-discrete;
	}

	.rowww-details-dialog:not([open]),
	.rowww-details-dialog:not([open])::backdrop {
		opacity: 0;
	}

	.rowww-details-dialog:not([open]) {
		transform: translateY(2rem);
	}

	@starting-style {

		.rowww-details-dialog[open],
		.rowww-details-dialog[open]::backdrop {
			opacity: 0;
		}

		.rowww-details-dialog[open] {
			transform: translateY(2rem);
		}
	}
}

.rowww-details-dialog__close {
	position: fixed;
	z-index: 2;
	top: var(--wp--preset--spacing--40);
	right: var(--wp--custom--gutter);
}

:is(.rowww-details-dialog__close, .rowww-details-dialog__arrow) {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--wp--preset--color--surface-alt);
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
	transition: background-color 200ms ease, opacity 200ms ease;
}

:is(.rowww-details-dialog__close, .rowww-details-dialog__arrow):is(:hover, :focus-visible) {
	background: color-mix(in srgb, var(--wp--preset--color--contrast) 30%, var(--wp--preset--color--base));
}

.rowww-details-dialog__arrow:disabled {
	opacity: 0.35;
	cursor: default;
}

.rowww-details-dialog__arrow.is-prev svg {
	transform: scaleX(-1);
}

.rowww-details-dialog .rowww-details {
	display: flex;
	flex: 1 0 auto;
	flex-direction: column;
	justify-content: center;
	min-width: 0;
	margin: 0;
}

.rowww-details > * {
	margin-block: 0;
}

.rowww-details__head {
	padding-inline: var(--rowww-details-inset);
}

.rowww-details__head > * {
	margin-block: 0;
}

.rowww-details__title.rowww-details__title {
	margin-top: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--xxl);
}

/* The slide row: one slide at a time snaps to the content edge; the next
 * one peeks in from the right. A grid with four shared rows (heading, text,
 * illustration, buttons): every slide takes them over as a subgrid, so the
 * headings, the texts and the illustrations line up from slide to slide,
 * whatever their length. */
.rowww-details__track.rowww-details__track {
	display: grid;
	grid-template-rows: auto auto 1fr auto;
	grid-auto-columns: auto;
	grid-auto-flow: column;
	gap: 0 var(--wp--preset--spacing--30);
	margin-top: var(--wp--preset--spacing--40);
	padding: 0 var(--rowww-details-inset) var(--wp--preset--spacing--30);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-padding-inline: var(--rowww-details-inset);
	scrollbar-width: none;
	overscroll-behavior-x: contain;
}

.rowww-details__track::-webkit-scrollbar {
	display: none;
}

.rowww-details__track:focus-visible {
	outline: 2px solid var(--rowww-accent-text-start);
	outline-offset: -2px;
}

.rowww-details__slide.rowww-details__slide {
	box-sizing: border-box;
	display: grid;
	grid-row: 1 / -1;
	grid-template-rows: subgrid;
	row-gap: var(--wp--preset--spacing--30);
	width: min(40rem, 84vw);
	margin: 0;
	padding: var(--wp--preset--spacing--50);
	border-radius: calc(var(--wp--preset--border-radius--card) * 1.5);
	background: var(--rowww-details-tone);
	scroll-snap-align: start;
	text-align: center;
}

.rowww-details__slide.is-wide {
	width: min(60rem, 84vw);
}

/* The illustration always takes the third row (a slide without a text
 * paragraph keeps its rows too), the buttons the fourth. */
.rowww-details__slide > .rowww-details__visual {
	grid-row: 3;
}

.rowww-details__slide > .rowww-details__buttons {
	grid-row: 4;
}

.rowww-details__slide > * {
	margin-block: 0;
}

.rowww-details__heading.rowww-details__heading {
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 600;
	letter-spacing: -0.01em;
	text-wrap: balance;
}

.rowww-details__text {
	max-width: 32rem;
	margin-inline: auto;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--md);
	text-wrap: pretty;
}

/* The illustration fills the rest of the slide, centred. */
.rowww-details__visual.rowww-details__visual {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--20);
	min-height: 16rem;
	padding-top: var(--wp--preset--spacing--40);
	text-align: start;
}

.rowww-details__visual > * {
	width: 100%;
	margin-block: 0;
}

.rowww-details__visual.is-requests > .rowww-request {
	max-width: 24rem;
}

.rowww-details__visual.is-requests > .rowww-request:nth-child(even) {
	align-self: flex-end;
	max-width: 22rem;
}

.rowww-details__visual.is-list .is-style-checklist {
	max-width: 26rem;
	font-size: var(--wp--preset--font-size--md);
}

.rowww-details__visual .wp-block-rowww-chat-demo {
	margin: 0;
}

/* The chat demo is drawn for a page section: a little smaller in a slide. */
@media (min-width: 782px) {

	.rowww-details__visual .wp-block-rowww-chat-demo {
		zoom: 0.82;
	}
}

.rowww-details__visual.is-stats {
	flex-direction: row;
	gap: var(--wp--preset--spacing--60);
}

.rowww-details__visual.is-stats > * {
	width: auto;
	text-align: center;
}

.rowww-details__stat > * {
	margin-block: 0;
}

.rowww-details__stat-label {
	color: var(--wp--preset--color--muted);
}

.rowww-details__stat-label strong {
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
}

/* What the chat knows: accent-tinted pills. */
.rowww-details__chips.rowww-details__chips {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--wp--preset--spacing--20);
	max-width: 28rem;
	padding: 0;
	list-style: none;
}

.rowww-details__chips > li {
	margin: 0;
	padding: 0.55rem 1.1rem;
	border: 1px solid color-mix(in srgb, var(--rowww-accent-start) 55%, transparent);
	border-radius: 999px;
	background: color-mix(in srgb, var(--rowww-accent-start) 14%, transparent);
	font-size: var(--wp--preset--font-size--base);
}

/* A single large icon on an accent disc with a soft light. */
.rowww-details__visual.is-icon .wp-block-rowww-icon {
	display: grid;
	place-items: center;
	width: 8rem;
	height: 8rem;
	border-radius: 50%;
	background:
		radial-gradient(circle at 30% 25%, color-mix(in srgb, var(--rowww-accent-end) 55%, transparent), transparent 65%),
		color-mix(in srgb, var(--rowww-accent-start) 22%, transparent);
	box-shadow:
		inset 0 0 0 1px color-mix(in srgb, var(--rowww-accent-start) 60%, transparent),
		0 2rem 5rem -1.5rem color-mix(in srgb, var(--rowww-accent-start) 80%, transparent);
	color: var(--wp--preset--color--contrast);
}

.rowww-details__visual.is-icon .wp-block-rowww-icon svg {
	width: 3.25rem;
	height: 3.25rem;
}

.rowww-details__buttons.rowww-details__buttons {
	justify-content: center;
}

/* Dots and arrows below the row; they stay in view at the bottom when the
 * slides are taller than the window. */
.rowww-details-dialog__nav {
	position: sticky;
	z-index: 2;
	bottom: 0;
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--10);
	padding: var(--wp--preset--spacing--30) var(--wp--custom--gutter) var(--wp--preset--spacing--20);
	background: linear-gradient(to bottom, transparent, var(--wp--preset--color--base) 60%);
}

.rowww-details-dialog__dots {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	height: 2.75rem;
	margin-inline-end: var(--wp--preset--spacing--20);
	padding: 0 1.1rem;
	border-radius: 999px;
	background: var(--wp--preset--color--surface-alt);
}

.rowww-details-dialog__dot {
	width: 0.5rem;
	height: 0.5rem;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: color-mix(in srgb, var(--wp--preset--color--contrast) 45%, transparent);
	cursor: pointer;
	transition: width 300ms ease, background-color 300ms ease;
}

.rowww-details-dialog__dot[aria-current="true"] {
	width: 1.75rem;
	background: var(--wp--preset--color--contrast);
}

/* Phones: the whole dialog (heading, slide, dots) fits on one screen, so
 * nothing needs scrolling up and down: a smaller title, tighter slides and
 * type, and lighter illustrations. The chat demo (the tallest one, which
 * would set the row for all slides) shows only the first round of the
 * conversation, without the preview card and the input line; the sample
 * requests show two of three; the chat samples are drawn smaller. */
@media (max-width: 781px) {

	.rowww-details-dialog {
		padding-top: var(--wp--preset--spacing--40);
	}

	.rowww-details-dialog__close {
		top: var(--wp--preset--spacing--30);
	}

	.rowww-details__title.rowww-details__title {
		margin-top: var(--wp--preset--spacing--10);
		font-size: var(--wp--preset--font-size--xl);
	}

	.rowww-details__track.rowww-details__track {
		margin-top: var(--wp--preset--spacing--30);
		padding-bottom: var(--wp--preset--spacing--20);
	}

	.rowww-details__slide.rowww-details__slide {
		row-gap: var(--wp--preset--spacing--20);
		padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30);
	}

	.rowww-details__heading.rowww-details__heading {
		font-size: var(--wp--preset--font-size--md);
	}

	.rowww-details__text {
		font-size: var(--wp--preset--font-size--sm);
	}

	.rowww-details__visual.rowww-details__visual {
		min-height: 0;
		padding-top: var(--wp--preset--spacing--20);
	}

	.rowww-details__visual :is(.wp-block-rowww-chat-demo__preview, .wp-block-rowww-chat-demo__input),
	.rowww-details__visual .wp-block-rowww-chat-demo__chat > .is-second,
	.rowww-details__visual.is-requests > .rowww-request:nth-child(n+3) {
		display: none;
	}

	.rowww-details__visual :is(.wp-block-rowww-chat-demo, .rowww-visitor-chat) {
		zoom: 0.75;
	}

	.rowww-details__visual.is-requests > .rowww-request {
		padding: var(--wp--preset--spacing--30);
	}

	.rowww-details__visual.is-list .is-style-checklist,
	.rowww-details__chips > li {
		font-size: var(--wp--preset--font-size--sm);
	}

	.rowww-details__visual.is-stats {
		gap: var(--wp--preset--spacing--50);
	}

	.rowww-details__visual.is-icon .wp-block-rowww-icon {
		width: 5.5rem;
		height: 5.5rem;
	}

	.rowww-details__visual.is-icon .wp-block-rowww-icon svg {
		width: 2.5rem;
		height: 2.5rem;
	}

	.rowww-details__buttons .wp-block-button__link {
		padding: 0.6rem 1.1rem;
		font-size: var(--wp--preset--font-size--sm);
	}

	.rowww-details-dialog__nav {
		padding-top: var(--wp--preset--spacing--20);
		padding-bottom: var(--wp--preset--spacing--20);
	}
}

/* Short phone screens (e.g. with the browser bars showing): the eyebrow
 * above the dialog title goes too, and the chat demo is drawn smaller. */
@media (max-width: 781px) and (max-height: 720px) {

	.rowww-details__head > .is-style-eyebrow {
		display: none;
	}

	.rowww-details__visual .wp-block-rowww-chat-demo {
		zoom: 0.66;
	}
}

/*
 * Page intro entrance outside the hero block (`rowww-intro` on the H1, e.g.
 * Pricing and the blog): the same entrance as the hero, played on load. The
 * plugin splits the title into words (rowww-core `Blocks\Intro_Render`), which
 * rise one after another; the heading's siblings follow (what stands before
 * it first, then what comes after, one by one), and in a two-column layout
 * the other column comes in alongside. Transform and opacity only; desktop
 * only (from 782px), without reduced motion; elsewhere all is in place.
 */
@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {

	body:not(.editor-styles-wrapper) .rowww-intro .rowww-word {
		display: inline-block;
		animation: rowww-intro-word 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
		animation-delay: calc(120ms + var(--rowww-i, 0) * 55ms);
	}

	/* A phrase of several words stays inline, so it breaks like the rest. */
	body:not(.editor-styles-wrapper) .rowww-intro .rowww-word.is-phrase {
		display: inline;
	}

	body:not(.editor-styles-wrapper) :has(> .rowww-intro) > :not(.rowww-intro),
	body:not(.editor-styles-wrapper) .wp-block-columns:has(> .wp-block-column > .rowww-intro) > .wp-block-column:not(:has(> .rowww-intro)) {

		/* Longhands, so the delays below (lower specificity) are kept. */
		animation-name: rowww-intro-in;
		animation-duration: 1s;
		animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
		animation-fill-mode: both;
	}

	body:not(.editor-styles-wrapper) .wp-block-columns:has(> .wp-block-column > .rowww-intro) > .wp-block-column:not(:has(> .rowww-intro)) {
		animation-delay: 350ms;
	}

	body:not(.editor-styles-wrapper) .rowww-intro ~ * {
		animation-delay: 550ms;
	}

	body:not(.editor-styles-wrapper) .rowww-intro ~ * ~ * {
		animation-delay: 700ms;
	}
}

@keyframes rowww-intro-word {

	from {
		opacity: 0;
		transform: translateY(0.35em);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes rowww-intro-in {

	from {
		opacity: 0;
		transform: translateY(1.5rem);
	}

	to {
		opacity: 1;
		transform: none;
	}
}
