/*
 * The product page.
 *
 * Section shells (.sx-home-block, .sx-tiles, .sx-tile) come from
 * home-sections.css, which every page already loads — only what is specific to
 * a product is here.
 */

.sx-product-page {
	padding-top: var( --wp--preset--spacing--50 );
}

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

.sx-product-hero {
	display: grid;
	grid-template-columns: minmax( 0, 1fr );
	gap: 40px;
	align-items: center;
	margin-bottom: var( --wp--preset--spacing--70 );
}

/*
 * One size for every product name. The old 48px display suited "BAS ERP" and
 * nothing else: most of the catalogue is named in full — edition, seat count,
 * configuration — and at that size those titles filled the screen. 34px reads
 * as the page's title rather than as a banner, whatever the name's length.
 *
 * This was raised to --sx-title-page once, to bring product pages onto the
 * same heading as everything else, and "BAS Комплексне управління
 * підприємством" immediately came back as three lines in a 607px column.
 * The catalogue names are the constraint, not the scale. It stays here.
 */
.sx-product-hero__title {
	margin: 10px 0 16px;
	font-size: var( --sx-title-page );
	line-height: 1.15;
	letter-spacing: -0.015em;
	/*
	 * A break of last resort. "Автосервіс+Автозапчастини," is one word to the
	 * line breaker — a plus sign is no break opportunity — and at this type
	 * size it pushed the whole page sideways on a phone. The template also
	 * puts a <wbr> after each plus, so this only catches what that misses.
	 */
	overflow-wrap: break-word;
}


/*
 * The short description. A block rather than a paragraph, because the field
 * behind it now takes a sentence and a list of selling points: one line per
 * item, a leading dash for a bullet. It used to be a single input, so a
 * description written that way arrived as one unbroken run of text with the
 * points welded onto the end of the sentence.
 */
.sx-product-hero__lead {
	margin: 0;
	max-width: 54ch;
	color: var( --sx-text-secondary );
	font-size: 1.0625rem;
	line-height: 1.6;
}

.sx-product-hero__lead p {
	margin: 0;
}

.sx-product-hero__lead p + p,
.sx-product-hero__lead p + .sx-product-hero__points {
	margin-top: 12px;
}

.sx-product-hero__points {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 8px;
}

.sx-product-hero__points li {
	position: relative;
	padding-left: 22px;
	font-size: 1rem;
	line-height: 1.5;
	overflow-wrap: break-word;
}

/* A square, the way the vendor's own sheets mark these lists — and small
   enough not to compete with the ✓ rows further down the page. */
.sx-product-hero__points li::before {
	content: "";
	position: absolute;
	left: 2px;
	top: 0.6em;
	width: 7px;
	height: 7px;
	border-radius: 2px;
	background: var( --sx-brand );
}

.sx-product-hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 20px;
	margin-top: 28px;
}

/* The figure the decision turns on, next to the button that acts on it. */
.sx-product-hero__price {
	margin: 28px 0 8px;
	font-size: 1.75rem;
	font-weight: 700;
	letter-spacing: -0.02em;
}

/* Reads as a footnote to the figure, not as part of it. */
.sx-product-hero__vat {
	margin-left: 6px;
	color: var( --sx-text-secondary );
	font-size: 0.875rem;
	font-weight: 500;
	letter-spacing: 0;
	white-space: nowrap;
}

/*
 * The unit a "від" price is quoted in. Carries the same weight as the VAT note
 * deliberately: it is not a footnote to the figure, it is what stops "від
 * 386,40 ₴" reading as the price of the whole product rather than of one seat.
 */
.sx-product-hero__unit {
	margin-left: 6px;
	color: var( --sx-text-secondary );
	font-size: 0.875rem;
	font-weight: 500;
	letter-spacing: 0;
	white-space: nowrap;
}

.sx-product-hero__note {
	margin: 0;
	max-width: 52ch;
	color: var( --sx-text-secondary );
	font-size: 0.875rem;
	line-height: 1.55;
}

/*
 * The pricing note normally follows the price, which carries its own space
 * above and below. A product with no price has neither, so the note ran
 * straight on from the description with nothing between them — the paragraph
 * about what the product does and the paragraph about what it costs read as
 * one block of text. Visible on the two budget products.
 */
.sx-product-hero__lead + .sx-product-hero__note {
	margin-top: 18px;
}

/*
 * Two buttons, one filled and one outlined: buying is the primary action and
 * asking is the alternative, so they carry different weight rather than
 * different shapes.
 */
.sx-product-hero__buy,
.sx-product-hero__consult {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: 48px;
	padding-inline: 26px;
	border-radius: var( --sx-radius-btn );
	font-size: 0.9375rem;
	font-weight: 600;
	text-decoration: none;
	cursor: pointer;
	transition: background-color var( --sx-transition-fast ) var( --sx-ease ),
		border-color var( --sx-transition-fast ) var( --sx-ease ),
		color var( --sx-transition-fast ) var( --sx-ease );
}

.sx-product-hero__buy {
	border: 1px solid var( --sx-brand );
	background: var( --sx-brand );
	color: var( --sx-white );
}

/*
 * The trolley is a background image rather than an inline <svg>: cart.js
 * confirms an add by swapping the button's textContent for "Додано" and back,
 * and any element inside would not survive that.
 */
.sx-product-hero__buy::before {
	content: "";
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	background: url( 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3h2l2.4 12h9.2L19 6H6"/><circle cx="9" cy="20" r="1.5" fill="white" stroke="none"/><circle cx="17" cy="20" r="1.5" fill="white" stroke="none"/></svg>' ) no-repeat center / contain;
}

.sx-product-hero__buy:hover {
	background: var( --sx-brand-hover );
	border-color: var( --sx-brand-hover );
	color: var( --sx-white );
}

.sx-product-hero__buy.is-added {
	background: var( --sx-brand-hover );
	border-color: var( --sx-brand-hover );
}

.sx-product-hero__consult {
	border: 1px solid var( --sx-border );
	background: var( --sx-white );
	color: var( --sx-text );
}

.sx-product-hero__consult:hover {
	border-color: var( --sx-brand-200 );
	color: var( --sx-brand-text );
}

.sx-product-hero__buy:focus-visible,
.sx-product-hero__consult:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 3px;
}

/* ---- The hero picture ----
   The image itself, with no drawn frame around it. It used to sit in a CSS
   laptop, which suited a screenshot of an interface but not the artwork these
   products actually have — a banner in a laptop reads as a picture of a
   picture. Whatever is uploaded is shown at its own proportions. */

.sx-product-hero__art img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var( --sx-radius-lg );
}

/*
 * Square box artwork, cropped back to the box.
 *
 * These files carry their own margin — the box occupies about 62% of a square
 * canvas — and in a two-column hero that margin is what sets the row's height,
 * leaving a deep band of nothing above the title and below the buttons. The
 * crop takes that margin off instead of shrinking the box, so the artwork
 * keeps the size it has and the row loses the emptiness.
 *
 * More is taken from the top than the bottom because that is how the file is
 * built: 21% empty above, 17% below. 60% of the overflow off the top lands the
 * box centred with a little air on each side and nothing clipped.
 */
.sx-product-hero__art--boxed {
	aspect-ratio: 1 / 0.68;
	overflow: hidden;
	border-radius: var( --sx-radius-lg );
}

.sx-product-hero__art--boxed img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 60%;
	border-radius: 0;
}

/*
 * Two columns only when there is a picture for the second one. Products
 * without a hero image were still splitting 46/54, so the title wrapped
 * inside a 607px column while the right half of the screen sat empty.
 *
 * :has() rather than a class from PHP, because the condition is already in
 * the markup. A browser too old for :has() gets one column, which is what
 * the phone layout is anyway.
 */
@media ( min-width: 901px ) {
	.sx-product-hero:has( .sx-product-hero__art ) {
		grid-template-columns: minmax( 0, 46% ) minmax( 0, 1fr );
		gap: 56px;
	}
}

/* ---- Quick jump bar ----
 *
 * Sticks to the top of the window once the opening screen has scrolled past.
 * Empty until the script fills it, and hidden while empty — the tabs need the
 * script both to animate the jump and to mark where the reader is.
 */

.sx-product-nav {
	display: none;
}

.sx-product-nav--ready {
	position: sticky;
	top: var( --sx-sticky-top );
	z-index: var( --sx-z-sticky );
	display: flex;
	gap: 8px;
	margin-bottom: var( --wp--preset--spacing--50 );
	border-bottom: 1px solid var( --sx-border );
	background-color: var( --sx-white );
	overflow-x: auto;
	scrollbar-width: none;
	/*
	 * A fade at the right edge where the row runs past the screen — on a phone
	 * six tabs do not fit, and a row that simply stops at the edge looks like
	 * the last tab is the last one there is. The gradient sits on the element,
	 * not the content, so it stays at the edge while the tabs scroll under it;
	 * .is-end takes it away once there is nothing more to reach.
	 */
	background-image: linear-gradient( to left, var( --sx-white ), rgba( 255, 255, 255, 0 ) );
	background-repeat: no-repeat;
	background-position: right center;
	background-size: 40px 100%;
}

.sx-product-nav--ready.is-end {
	background-image: none;
}

.sx-product-nav--ready::-webkit-scrollbar {
	display: none;
}

.sx-product-nav--ready::-webkit-scrollbar {
	display: none;
}

.sx-product-nav__tab {
	flex: 0 0 auto;
	padding: 16px 20px;
	border-bottom: 2px solid transparent;
	color: var( --sx-text-secondary );
	font-size: 0.9375rem;
	font-weight: 600;
	text-decoration: none !important;
	white-space: nowrap;
	transition: color var( --sx-transition-fast ) var( --sx-ease ),
		border-color var( --sx-transition-fast ) var( --sx-ease );
}

.sx-product-nav__tab:hover {
	color: var( --sx-text );
}

.sx-product-nav__tab.is-current {
	border-bottom-color: var( --sx-brand-text );
	color: var( --sx-brand-text );
}

.sx-product-nav__tab:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: -4px;
}

/*
 * On a phone the tabs wrap, and the type is small enough that eight of them
 * take two rows rather than three. Both extremes have been tried and sent
 * back: three rows held a third of the screen at the top, one scrolling row
 * hid half the sections off the right edge. Two rows show every section at
 * once and cost 73px.
 */
@media ( max-width: 780px ) {
	.sx-product-nav--ready {
		flex-wrap: wrap;
		gap: 0;
		overflow-x: visible;
		/* Nothing runs past the edge now, so the fade has nothing to stand for. */
		background-image: none;
	}

	.sx-product-nav__tab {
		padding: 8px 10px;
		font-size: 0.75rem;
	}

}

/*
 * Where a jump lands. The bar itself is ~54px tall and covers the top of the
 * window, so a section scrolled to 0 would start underneath it.
 */
.single-product .sx-home-block,
.single-product .sx-product-content {
	scroll-margin-top: 72px;
}

/*
 * Room for the admin bar, but only on the widths where WordPress actually
 * fixes it over the page. Below 783px it makes that bar position:absolute, so
 * it scrolls away with the content — and holding the tabs 46px down from the
 * top left a strip of the page showing above them once it had gone. 783px is
 * WordPress's own breakpoint for the switch, not a round number of ours.
 */
@media ( min-width: 783px ) {
	/* --sx-sticky-top already counts the admin bar, and from 1200px the site
	   header as well. This rule used to name the admin bar on its own, which was
	   right when the header scrolled away and wrong the moment it started
	   sticking: being later in the file, it quietly won over the rule above. */
	.sx-product-nav--ready {
		top: var( --sx-sticky-top );
	}

	.single-product .sx-home-block,
	.single-product .sx-product-content {
		scroll-margin-top: calc( 72px + var( --sx-sticky-top ) );
	}
}

/*
 * The phone's bar is two rows, so a jump has to clear more. This has to come
 * after the rule above, not with the rest of the narrow-screen styles: both
 * match at this width, and where they tie the later one wins — which is how
 * the two-row bar once ended up landing sections 28px too high.
 */
@media ( max-width: 780px ) {
	.single-product .sx-home-block,
	.single-product .sx-product-content {
		scroll-margin-top: 90px;
	}
}

/* ---- 01a Ключові переваги ----
 *
 * Two columns on a desktop, one on a phone. A single column of nine one-liners
 * runs down half a screen with the right two thirds empty; cards would be
 * worse — these are read as one answer, not nine.
 */

.sx-benefits {
	display: grid;
	grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	gap: 14px 40px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.sx-benefits__item {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	font-size: 1rem;
	line-height: 1.5;
}

.sx-benefits__tick {
	flex: 0 0 auto;
	display: inline-flex;
	/* Optically centred on the first line rather than on the box: the text can
	   run to two lines and the tick belongs beside the first one. */
	margin-top: 1px;
	color: var( --sx-brand-text );
}

@media ( max-width: 780px ) {
	.sx-benefits {
		grid-template-columns: minmax( 0, 1fr );
	}
}

/* ---- 02 Для кого ----
 *
 * One row of cards that scrolls, same as the tasks and the modules below. The
 * cards keep the tile look they had in the grid; only the container changed.
 */

.sx-audience {
	display: flex;
	gap: 24px;
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	scroll-behavior: smooth;
}

.sx-audience::-webkit-scrollbar {
	display: none;
}

.sx-audience:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 6px;
	border-radius: var( --sx-radius-lg );
}

.sx-audience-card {
	flex: 0 0 calc( ( 100% - 3 * 24px ) / 4 );
	scroll-snap-align: start;
	/* The editor's list spacing would push every card but the first down. */
	margin: 0 !important;
}

@media ( max-width: 1100px ) {
	.sx-audience-card {
		flex-basis: calc( ( 100% - 2 * 24px ) / 3 );
	}
}

@media ( max-width: 860px ) {
	.sx-audience-card {
		flex-basis: calc( ( 100% - 24px ) / 2 );
	}
}

@media ( max-width: 560px ) {
	.sx-audience-card {
		flex-basis: 82%;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.sx-audience {
		scroll-behavior: auto;
	}
}

.sx-audience-card__icon {
	display: inline-flex;
	color: var( --sx-brand-text );
}

.sx-audience-card__icon svg {
	width: 26px;
	height: 26px;
}

.sx-audience-card__problem {
	margin: 0;
	color: var( --sx-text-secondary );
	font-size: 0.9375rem;
	line-height: 1.55;
}

/* The answer is what the visitor came for, so it is the darker of the two. */
.sx-audience-card__answer {
	margin: 10px 0 0;
	padding-top: 10px;
	border-top: 1px solid var( --sx-border );
	font-size: 0.9375rem;
	line-height: 1.55;
}

/* ---- 03 Задачі ----
 *
 * One row of cards, chevrons in the gaps between them: the section reads as a
 * sequence of what the product covers rather than a stack of rows. The row
 * scrolls on its own, and product-page.js turns it into a looping carousel as
 * soon as the cards stop fitting.
 */

.sx-tasks {
	display: flex;
	gap: 28px;
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	scroll-behavior: smooth;
}

.sx-tasks::-webkit-scrollbar {
	display: none;
}

.sx-tasks:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 6px;
	border-radius: var( --sx-radius-lg );
}

.sx-task {
	position: relative;
	flex: 0 0 calc( ( 100% - 5 * 28px ) / 6 );
	scroll-snap-align: start;
	/* The list margin the editor gives every item but the first — in a row it
	   would push all but one card down. Same trap as the module row. */
	margin: 0 !important;
	padding: 22px 20px;
	border: 1px solid var( --sx-border );
	border-radius: var( --sx-radius-lg );
	background: var( --sx-white );
	transition: border-color var( --sx-transition-fast ) var( --sx-ease ),
		box-shadow var( --sx-transition-fast ) var( --sx-ease );
}

.sx-task:hover {
	border-color: var( --sx-brand-200 );
	box-shadow: var( --sx-shadow-card );
}

/* Drawn in the gap, not inside the card, so the row reads as one sequence. */
.sx-task:not( :last-child )::after {
	content: "";
	position: absolute;
	top: 50%;
	right: -19px;
	width: 8px;
	height: 8px;
	margin-top: -4px;
	border-top: 2px solid var( --sx-brand );
	border-right: 2px solid var( --sx-brand );
	transform: rotate( 45deg );
	opacity: 0.5;
}

.sx-task__icon {
	display: inline-flex;
	margin-bottom: 14px;
	color: var( --sx-brand-text );
}

.sx-task__icon svg {
	width: 26px;
	height: 26px;
}

.sx-task__title {
	margin: 0;
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1.35;
}

.sx-task__text {
	margin: 8px 0 0;
	color: var( --sx-text-secondary );
	font-size: 0.8125rem;
	line-height: 1.5;
}

@media ( max-width: 1100px ) {
	.sx-task {
		flex-basis: calc( ( 100% - 3 * 28px ) / 4 );
	}
}

@media ( max-width: 900px ) {
	.sx-task {
		flex-basis: calc( ( 100% - 2 * 28px ) / 3 );
	}
}

@media ( max-width: 700px ) {
	.sx-task {
		flex-basis: calc( ( 100% - 28px ) / 2 );
	}
}

@media ( max-width: 520px ) {
	.sx-task {
		flex-basis: 76%;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.sx-tasks {
		scroll-behavior: auto;
	}
}

/* ---- 04 Можливості ---- */

.sx-feature-card__icon {
	display: inline-flex;
	color: var( --sx-brand-text );
}

.sx-feature-card__icon svg {
	width: 26px;
	height: 26px;
}

.sx-feature-card {
	transition: transform var( --sx-transition-fast ) var( --sx-ease ),
		box-shadow var( --sx-transition-fast ) var( --sx-ease ),
		border-color var( --sx-transition-fast ) var( --sx-ease );
}

.sx-feature-card:hover {
	transform: translateY( -4px );
	border-color: var( --sx-brand-200 );
	box-shadow: var( --sx-shadow-card-hover );
}

/*
 * The modules as one scrolling row. Four fit on a desktop, less as the window
 * narrows; the row keeps its own scrolling so it works without the script, and
 * the arrows and the wrap-around come from product-page.js.
 */
.sx-modules {
	display: flex;
	gap: 20px;
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	/*
	 * Proximity, not mandatory. The loop moves the scroll position by a whole
	 * copy's width when the row runs into the duplicate, and mandatory snapping
	 * hauls it straight back to the card it had snapped to before the move —
	 * which is what sent the row back to the first card on every wrap.
	 */
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	scroll-behavior: smooth;
}

.sx-modules::-webkit-scrollbar {
	display: none;
}

.sx-modules:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 6px;
	border-radius: var( --sx-radius-lg );
}

.sx-modules__item {
	flex: 0 0 calc( ( 100% - 60px ) / 4 );
	scroll-snap-align: start;
	display: flex;
	/*
	 * Every list item but the first was picking up a 12px top margin — one
	 * block gap, the spacing meant for items stacked in a column. In this row
	 * it pushed all but the first card down, leaving the first one standing a
	 * size taller than the rest.
	 *
	 * !important because whatever applies it outranks a plain ".sx-modules >
	 * li" (measured: that selector loses, this one wins), and it is not in the
	 * theme's own stylesheets — it comes with the editor's list styling.
	 */
	margin: 0 !important;
}

/* All the cards in the row stand the same height, whatever the length of the
   name — a row of boxes ending at four different heights reads as broken. */
.sx-modules__item > * {
	width: 100%;
	height: 100%;
}

@media ( max-width: 1100px ) {
	.sx-modules__item {
		flex-basis: calc( ( 100% - 40px ) / 3 );
	}
}

@media ( max-width: 820px ) {
	.sx-modules__item {
		flex-basis: calc( ( 100% - 20px ) / 2 );
	}
}

@media ( max-width: 560px ) {
	.sx-modules__item {
		flex-basis: 78%;
	}
}

/*
 * On a phone the card rows stop being rows.
 *
 * Three sideways-scrolling strips one under another (audience, tasks, modules)
 * meant most of a product page moved left and right under the thumb, and each
 * strip showed one card and the edge of the next — the page read as something
 * that would not sit still. Stacked, every card is full width and the only
 * direction left is down.
 *
 * The script reads this too: setupCarousel() gives up on a track that already
 * fits, so no arrows are drawn and the looping rows are not duplicated.
 *
 * The screenshot strip (.sx-shots) is deliberately left alone — a row of
 * pictures is expected to swipe, and one of those is not a page that wanders.
 */
@media ( max-width: 560px ) {
	.sx-audience,
	.sx-tasks,
	.sx-modules {
		display: grid;
		grid-template-columns: minmax( 0, 1fr );
		overflow-x: visible;
		scroll-snap-type: none;
	}

	.sx-audience-card,
	.sx-task,
	.sx-modules__item {
		min-width: 0;
	}

	/*
	 * The arrow between two tasks turns to face the way the sequence now runs.
	 * Left pointing right it also stuck 19px past the card's edge, which was
	 * enough overflow to convince the script the row still needed scrolling.
	 */
	.sx-task:not( :last-child )::after {
		top: auto;
		right: auto;
		bottom: -18px;
		left: 50%;
		margin: 0 0 0 -4px;
		transform: rotate( 135deg );
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.sx-modules {
		scroll-behavior: auto;
	}
}

/* Each card jumps to that module's own description further down the page. */
.sx-feature-card--link {
	color: inherit;
	text-decoration: none !important;
	cursor: pointer;
	/*
	 * A module card carries a name and nothing else, and the shared tile's
	 * 200px floor left two thirds of each one empty — with fifteen of them that
	 * is a screen and a half of white space. They size to their content here;
	 * the grid still squares off the rows.
	 */
	min-height: 0;
	gap: 12px;
}

.sx-feature-card--link:hover .sx-tile__title,
.sx-feature-card--link:focus-visible .sx-tile__title {
	color: var( --sx-brand-text );
}

.sx-feature-card--link:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 3px;
}

/*
 * Where a card lands. Without the margin the module's own heading sits under
 * the sticky header on a desktop, and right against the top edge on a phone —
 * the reader arrives at an open panel with its title out of sight.
 */
.sx-product-content .softextheme-faq__item[ id ] {
	scroll-margin-top: 96px;
}

/* ---- 05 Інтерфейс продукту ----
 *
 * Two columns per the kit: the copy and the "all screenshots" button hold the
 * left, the carousel takes the rest.
 */

.sx-product-shots__intro .sx-home-block__head {
	display: block;
	margin-bottom: 24px;
}

.sx-product-shots__all {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 12px 20px;
	border: 1px solid var( --sx-border );
	border-radius: var( --sx-radius-btn );
	background: var( --sx-white );
	color: var( --sx-text );
	font-size: 0.9375rem;
	font-weight: 600;
	cursor: pointer;
	transition: border-color var( --sx-transition-fast ) var( --sx-ease ),
		color var( --sx-transition-fast ) var( --sx-ease ),
		box-shadow var( --sx-transition-fast ) var( --sx-ease );
}

.sx-product-shots__all:hover {
	border-color: var( --sx-brand-200 );
	color: var( --sx-brand-text );
	box-shadow: var( --sx-shadow-card );
}

.sx-product-shots__all:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 2px;
}

@media ( min-width: 901px ) {
	.sx-product-shots {
		display: grid;
		grid-template-columns: minmax( 220px, 320px ) minmax( 0, 1fr );
		gap: 56px;
		align-items: center;
	}
}

@media ( max-width: 900px ) {
	.sx-product-shots__all {
		margin-bottom: 28px;
	}
}

/* ---- The carousel ---- */

/*
 * The wrapper exists so the arrows have something to be positioned against.
 * The scrolling itself stays on the list — the arrows only nudge it, so a
 * swipe, a wheel and a click all end up in the same place.
 */
.sx-carousel {
	position: relative;
}

.sx-shots {
	display: flex;
	gap: 20px;
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	scroll-behavior: smooth;
}

.sx-shots:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 6px;
	border-radius: var( --sx-radius-lg );
}

.sx-carousel__nav {
	position: absolute;
	top: calc( 50% - 22px );
	z-index: 2;
	display: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1px solid var( --sx-border );
	border-radius: 50%;
	background: var( --sx-white );
	color: var( --sx-text );
	box-shadow: var( --sx-shadow-card );
	cursor: pointer;
	transition: opacity var( --sx-transition-fast ) var( --sx-ease ),
		transform var( --sx-transition-fast ) var( --sx-ease ),
		border-color var( --sx-transition-fast ) var( --sx-ease );
}

/* Only once the script has actually wired them up. */
.sx-carousel--ready .sx-carousel__nav {
	display: inline-flex;
}

/*
 * Outside the row by default: over a row of cards an arrow covers the very
 * name it is meant to help reach.
 */
.sx-carousel__nav--prev {
	left: -20px;
}

.sx-carousel__nav--next {
	right: -20px;
}

/* The gallery is the exception — there they sit over the dimmed neighbours, as
   in the kit; outside the frame they would push the pictures inwards and cost
   the carousel its width. */
.sx-product-shots .sx-carousel__nav--prev {
	left: 10px;
}

.sx-product-shots .sx-carousel__nav--next {
	right: 10px;
}

.sx-carousel__nav:hover {
	border-color: var( --sx-brand-200 );
	color: var( --sx-brand-text );
}

.sx-carousel__nav:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 2px;
}

/*
 * Kept in place rather than hidden at the ends: arrows that disappear make the
 * row jump sideways, and the reader loses the control they were aiming at.
 */
.sx-carousel__nav[ disabled ] {
	opacity: 0.35;
	cursor: default;
	box-shadow: none;
}

.sx-carousel__dots {
	display: none;
	justify-content: center;
	gap: 8px;
	margin-top: 20px;
}

.sx-carousel--ready .sx-carousel__dots {
	display: flex;
}

.sx-carousel__dot {
	width: 8px;
	height: 8px;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: var( --sx-border-strong );
	cursor: pointer;
	transition: width var( --sx-transition-fast ) var( --sx-ease ),
		background-color var( --sx-transition-fast ) var( --sx-ease );
}

.sx-carousel__dot.is-current {
	width: 24px;
	background: var( --sx-brand );
}

.sx-carousel__dot:focus-visible {
	outline: 2px solid var( --sx-brand );
	outline-offset: 3px;
}

/* On a phone the arrows would sit on top of the picture; the swipe and the
   dots carry it there. */
@media ( max-width: 780px ) {
	.sx-carousel--ready .sx-carousel__nav {
		display: none;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.sx-shots {
		scroll-behavior: auto;
	}
}

.sx-shots::-webkit-scrollbar {
	display: none;
}

/*
 * Centred, not left-aligned: the kit shows the picture in the middle with its
 * neighbours peeking in from both sides, so the row reads as a carousel
 * standing still rather than a list cut off at the right.
 */
.sx-shots__item {
	flex: 0 0 min( 560px, 76% );
	scroll-snap-align: center;
	/* Same list spacing as the module row — see the note there. */
	margin: 0 !important;
	opacity: 0.45;
	transform: scale( 0.94 );
	transition: opacity var( --sx-transition-base ) var( --sx-ease ),
		transform var( --sx-transition-base ) var( --sx-ease );
}

/* Until the script names one, every slide is a full one — a page without it
   would otherwise show a row of faded pictures and no way to fix that. */
.sx-carousel:not( .sx-carousel--ready ) .sx-shots__item,
.sx-shots__item.is-current {
	opacity: 1;
	transform: none;
}

@media ( prefers-reduced-motion: reduce ) {
	.sx-shots__item {
		transition: none;
	}
}

.sx-shots__btn {
	display: block;
	width: 100%;
	padding: 0;
	border: 1px solid var( --sx-border );
	border-radius: var( --sx-radius-lg );
	background: var( --sx-surface );
	overflow: hidden;
	cursor: zoom-in;
	transition: border-color var( --sx-transition-fast ) var( --sx-ease ),
		box-shadow var( --sx-transition-fast ) var( --sx-ease );
}

.sx-shots__btn:hover {
	border-color: var( --sx-border-strong );
	box-shadow: var( --sx-shadow-card );
}

/* Every shot in the same frame, whatever the file's own proportions — a row of
   mismatched rectangles reads as a mistake. */
.sx-shots__btn img {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 10;
	height: auto;
	object-fit: cover;
	object-position: top center;
}

/* ---- Lightbox ---- */

.sx-lightbox {
	position: fixed;
	inset: 0;
	z-index: var( --sx-z-overlay );
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 32px;
	border: 0;
	background: rgba( 17, 19, 24, 0.88 );
	/*
	 * The browser's own <dialog> rules size it to its content and centre it
	 * with automatic margins — "inset: 0" alone left a box the size of the
	 * picture floating in the middle of the page, with the page itself visible
	 * around it. These four make it the whole window.
	 */
	width: 100%;
	height: 100%;
	max-width: 100%;
	max-height: 100%;
	margin: 0;
}

/* The window behind it is covered by the dialog itself, but a dialog opened
   with showModal() also paints a backdrop — matching it keeps the edges from
   showing a lighter seam on browsers that inset the dialog slightly. */
.sx-lightbox::backdrop {
	background: rgba( 17, 19, 24, 0.88 );
}

/* Paging through the gallery without leaving the lightbox — what the "all
   screenshots" button promises. */
.sx-lightbox__nav {
	position: absolute;
	top: 50%;
	transform: translateY( -50% );
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba( 255, 255, 255, 0.12 );
	color: var( --sx-white );
	cursor: pointer;
	transition: background-color var( --sx-transition-fast ) var( --sx-ease );
}

.sx-lightbox__nav:hover {
	background: rgba( 255, 255, 255, 0.24 );
}

.sx-lightbox__nav--prev {
	left: 20px;
}

.sx-lightbox__nav--next {
	right: 20px;
}

.sx-lightbox__count {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 24px;
	margin: 0;
	color: rgba( 255, 255, 255, 0.7 );
	font-size: 0.875rem;
	text-align: center;
}

.sx-lightbox img {
	max-width: 100%;
	max-height: 100%;
	border-radius: var( --sx-radius-md );
}

.sx-lightbox__close {
	position: absolute;
	top: 16px;
	right: 20px;
	width: 44px;
	height: 44px;
	border: 0;
	border-radius: 50%;
	background: rgba( 255, 255, 255, 0.14 );
	color: var( --sx-white );
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
}

.sx-lightbox__close:hover {
	background: rgba( 255, 255, 255, 0.24 );
}

/* ---- 06 Результат ---- */

.sx-outcomes {
	display: grid;
	grid-template-columns: repeat( 4, minmax( 0, 1fr ) );
	gap: 8px;
	padding: 8px;
	border: 1px solid var( --sx-border );
	border-radius: var( --sx-radius-lg );
	background: var( --sx-white );
}

.sx-outcome {
	position: relative;
	padding: 20px 22px;
}

.sx-outcome + .sx-outcome::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	top: 20%;
	height: 60%;
	border-inline-start: 1px solid var( --sx-border );
}

.sx-outcome__value {
	display: block;
	font-size: 1.75rem;
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.02em;
}

.sx-outcome__label {
	display: block;
	margin-top: 4px;
	color: var( --sx-text-secondary );
	font-size: 0.875rem;
	line-height: 1.4;
}

@media ( max-width: 900px ) {
	.sx-outcomes {
		grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	}

	.sx-outcome:nth-child( odd )::before {
		content: none;
	}
}

@media ( max-width: 520px ) {
	.sx-outcomes {
		grid-template-columns: minmax( 0, 1fr );
	}

	.sx-outcome::before {
		content: none;
	}
}

/* ---- 08 Вартість: the price table ----
 *
 * Its own markup rather than the description's table block, so it spans the
 * section instead of the 900px reading measure the description is held to.
 */

.sx-price-table {
	border: 1px solid var( --sx-border );
	border-radius: var( --sx-radius-lg );
	/* Auto, not hidden: a long price list has to scroll on a phone rather than
	   be clipped. The radius still trims the corners. */
	overflow: auto;
}

.sx-price-table table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.9375rem;
}

.sx-price-table th,
.sx-price-table td {
	border: 0;
	padding: 14px 20px;
	text-align: left;
}

.sx-price-table thead th {
	background: var( --sx-surface );
	border-bottom: 1px solid var( --sx-border );
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.02em;
}

.sx-price-table tbody td {
	border-bottom: 1px solid var( --sx-border );
}

.sx-price-table tbody tr:last-child td {
	border-bottom: 0;
}

.sx-price-table tbody tr:hover {
	background: var( --sx-neutral-50 );
}

/* Figures line up on their last digit, which is the only way a column of
   prices can be compared at a glance. The column asks for its own width and no
   more, so the names keep the rest. */
.sx-price-table th:last-child,
.sx-price-table td:last-child {
	width: 1%;
	padding-left: 40px;
	text-align: right;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.sx-price-table tbody td:last-child {
	font-weight: 600;
}

@media ( max-width: 600px ) {
	.sx-price-table table {
		font-size: 0.875rem;
	}

	.sx-price-table th,
	.sx-price-table td {
		padding: 12px 14px;
	}

	.sx-price-table th:last-child,
	.sx-price-table td:last-child {
		padding-left: 14px;
	}
}

/* ---- 09 Поширені питання ----
 *
 * Two columns per the kit: the heading holds the left, the questions stack on
 * the right as separate rounded rows on a tinted panel. The shared accordion
 * (faq.css) is a plain bordered list — everything below reshapes that one
 * block without touching how it looks anywhere else on the site.
 */

.sx-product-faq .softextheme-faq {
	margin-top: 0;
	padding: 8px;
	border-radius: var( --sx-radius-lg );
	background: var( --sx-surface );
}

.sx-product-faq .softextheme-faq__item,
.sx-product-faq .softextheme-faq__item:first-child {
	border: 0;
	border-radius: 12px;
	background: var( --sx-white );
}

.sx-product-faq .softextheme-faq__item + .softextheme-faq__item {
	margin-top: 6px;
}

.sx-product-faq .softextheme-faq__question {
	gap: 20px;
	padding: 16px 20px;
	font-size: 0.9375rem;
	text-align: left;
}

/*
 * products.css puts a folder emoji before every question on a product page —
 * meant for the module accordion in the description. In this block it was also
 * what pushed the question text into the middle of the row: three flex items
 * with space-between leaves the middle one centred. The extra class beats that
 * rule, which otherwise has the same specificity as this one.
 */
.sx-product-faq .softextheme-faq .softextheme-faq__question::before {
	content: none;
}

/* The question takes the room, the chevron stays at the right edge — without
   this the label centres itself between the two flex items. */
.sx-product-faq .softextheme-faq__question > span:first-child {
	flex: 1 1 auto;
}

/*
 * A chevron rather than the shared plus/minus: the kit's rows open downwards
 * and the arrow says so. Drawn from two borders on the same box the plus used,
 * so the markup is unchanged.
 */
.sx-product-faq .softextheme-faq__icon {
	width: 16px;
	height: 16px;
	color: var( --sx-text-secondary );
}

.sx-product-faq .softextheme-faq__icon::before {
	width: 8px;
	height: 8px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	background: none;
	transform: translate( -50%, -70% ) rotate( 45deg );
	transition: transform var( --sx-transition-fast ) var( --sx-ease );
}

.sx-product-faq .softextheme-faq__icon::after {
	content: none;
}

.sx-product-faq .softextheme-faq__item[ open ] .softextheme-faq__icon::before {
	transform: translate( -50%, -30% ) rotate( -135deg );
}

.sx-product-faq .softextheme-faq__answer {
	padding: 0 20px 18px;
}

@media ( min-width: 901px ) {
	.sx-product-faq {
		display: grid;
		grid-template-columns: minmax( 200px, 300px ) minmax( 0, 1fr );
		gap: 56px;
		align-items: start;
	}

	/* The head is a column now, not a row above the content. */
	.sx-product-faq .sx-home-block__head {
		display: block;
		margin-bottom: 0;
	}
}

/* ---- 08 Вартість ---- */

.sx-pricing-card {
	display: grid;
	grid-template-columns: minmax( 0, 1fr ) auto;
	align-items: center;
	gap: 32px;
	padding: 28px 32px;
	border-radius: var( --sx-radius-lg );
	background: var( --sx-surface );
}

.sx-pricing-card__price {
	margin: 0 0 8px;
	font-size: 1.75rem;
	font-weight: 700;
	letter-spacing: -0.02em;
}

.sx-pricing-card__note {
	margin: 0;
	max-width: 62ch;
	color: var( --sx-text-secondary );
	font-size: 0.9375rem;
	line-height: 1.55;
}

.sx-pricing-card__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
}

.sx-pricing-card__cta {
	padding-inline: 26px;
	border-radius: var( --sx-radius-btn );
	background: var( --sx-brand );
	color: var( --sx-white );
	font-size: 0.9375rem;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}

.sx-pricing-card__cta:hover {
	background: var( --sx-brand-hover );
	color: var( --sx-white );
}

@media ( max-width: 900px ) {
	.sx-pricing-card {
		grid-template-columns: minmax( 0, 1fr );
		padding: 24px;
	}
}

/* ---- The description ----
 *
 * Everything an editor writes in the post editor lands here, so these rules
 * dress plain headings, lists, tables and accordions rather than classes the
 * theme controls — a new heading or table added tomorrow comes out styled.
 *
 * The selectors are doubled up on purpose: products.css already styles the same
 * elements from `.single-product`, and its version of the table is a solid red
 * header with a drop shadow, which belongs to no other surface on this site.
 */

.sx-product-content {
	max-width: 900px;
	font-size: 1.0625rem;
	line-height: 1.7;
	/*
	 * The hero title already breaks at its plus signs, but the same product name
	 * is written out again in the body copy — "«Альфа-Авто: Автосалон+Автосервіс
	 * +Автозапчастини, редакція 6»" — where it is prose, not a title, and no
	 * <wbr> is inserted. At 320px that one paragraph took the page 54px sideways.
	 */
	overflow-wrap: break-word;
}

.sx-product-content > * {
	max-width: 100%;
}

/*
 * One level deeper than products.css needs, on purpose. Its rules for the same
 * headings carry the same specificity as a plain `.sx-product-content h3`, so
 * which one won came down to the order two stylesheets happened to load in —
 * and it was the other one.
 */
.single-product .sx-product-content .entry-content h2,
.single-product .sx-product-content .entry-content h3,
.single-product .sx-product-content .wp-block-post-content h2,
.single-product .sx-product-content .wp-block-post-content h3 {
	display: block;
	margin: 2.4em 0 0.8em;
	font-size: 1.5rem;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.01em;
}

/* No bar before the heading: no other section title on the site has one. */
.single-product .sx-product-content .entry-content h2::before,
.single-product .sx-product-content .entry-content h3::before,
.single-product .sx-product-content .wp-block-post-content h2::before,
.single-product .sx-product-content .wp-block-post-content h3::before {
	content: none;
}

.sx-product-content p {
	margin: 0 0 1.2em;
	color: var( --sx-text-secondary );
}

/* ---- Lists ---- */

.single-product .sx-product-content ul {
	margin: 0 0 1.4em;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 12px;
}

.single-product .sx-product-content ul li {
	position: relative;
	padding-left: 32px;
	font-size: 0.9375rem;
	line-height: 1.55;
}

/* The kit's circled tick, as a background — the list comes from the editor and
   there is nowhere in it to put an <svg>. */
.single-product .sx-product-content ul li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 1px;
	width: 20px;
	height: 20px;
	background: url( 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23e32621" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>' ) no-repeat center / contain;
}

.single-product .sx-product-content ul li::marker {
	content: none;
}

/* ---- Tables ---- */

.single-product .sx-product-content .wp-block-table {
	margin: 0 0 1.6em;
	border: 1px solid var( --sx-border );
	border-radius: var( --sx-radius-lg );
	box-shadow: none;
	/* Not hidden: a wide price list has to be scrollable on a phone rather than
	   clipped. The radius still trims the corners. */
	overflow: auto;
}

.single-product .sx-product-content .wp-block-table table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.9375rem;
}

/*
 * Core draws the table as a grid — `border: 1px solid` on every cell and a
 * 3px rule under the head, both in currentColor, so the price list came out
 * boxed in near-black lines. Only the horizontal hairlines below are wanted;
 * these two rules clear everything else first, since a per-cell border can't
 * be overridden by styling the row or the head.
 */
.single-product .sx-product-content .wp-block-table thead,
.single-product .sx-product-content .wp-block-table tfoot,
.single-product .sx-product-content .wp-block-table tr {
	border: 0;
}

.single-product .sx-product-content .wp-block-table th,
.single-product .sx-product-content .wp-block-table td {
	border: 0;
}

/* A quiet header on the surface grey, not a red band: the red is the site's
   single accent and a table is not the place to spend it. */
.single-product .sx-product-content .wp-block-table thead th {
	padding: 14px 20px;
	background: var( --sx-surface );
	border-bottom: 1px solid var( --sx-border );
	color: var( --sx-text );
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-align: left;
}

.single-product .sx-product-content .wp-block-table tbody td {
	padding: 13px 20px;
	border-bottom: 1px solid var( --sx-border );
}

.single-product .sx-product-content .wp-block-table tbody tr:last-child td {
	border-bottom: 0;
}

.single-product .sx-product-content .wp-block-table tbody tr:nth-child( even ) {
	background: transparent;
}

.single-product .sx-product-content .wp-block-table tbody tr:hover {
	background: var( --sx-neutral-50 );
}

/* Figures line up on their last digit, which is the only way a column of
   prices can be compared at a glance. */
.single-product .sx-product-content .wp-block-table td:last-child,
.single-product .sx-product-content .wp-block-table th:last-child {
	text-align: right;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/* The figure is what the row is read for. */
.single-product .sx-product-content .wp-block-table tbody td:last-child {
	font-weight: 600;
}

/* The price column asks for exactly its own width and no more, so the names
   keep the rest instead of the two columns splitting the table in half. */
.single-product .sx-product-content .wp-block-table th:last-child,
.single-product .sx-product-content .wp-block-table td:last-child {
	width: 1%;
	padding-left: 40px;
}

/* On a phone the gap between the two columns is width the names need more:
   with it, "Клієнтська ліцензія для 100 користувачів" broke over four lines. */
@media ( max-width: 600px ) {
	.single-product .sx-product-content .wp-block-table table {
		font-size: 0.875rem;
	}

	.single-product .sx-product-content .wp-block-table thead th,
	.single-product .sx-product-content .wp-block-table tbody td {
		padding: 12px 14px;
	}

	.single-product .sx-product-content .wp-block-table th:last-child,
	.single-product .sx-product-content .wp-block-table td:last-child {
		padding-left: 14px;
	}
}

/* ---- Accordions inside the description ---- */

.single-product .sx-product-content .softextheme-faq__item {
	padding-left: 0;
	border: 1px solid var( --sx-border );
	border-radius: var( --sx-radius-md );
	margin-bottom: 10px;
	background: var( --sx-white );
}

.single-product .sx-product-content .softextheme-faq__question {
	padding: 16px 20px;
	font-size: 1rem;
	font-weight: 600;
	cursor: pointer;
}

/* The folder emoji this used to carry is the one multicolour glyph on the
   site, and the kit rules those out. */
.single-product .sx-product-content .softextheme-faq__question::before {
	content: none;
}

.single-product .sx-product-content .softextheme-faq__answer {
	padding: 0 20px 18px;
}

.single-product .sx-product-content .softextheme-faq__answer p {
	margin: 0 0 0.9em;
	font-size: 0.9375rem;
}

.single-product .sx-product-content .softextheme-faq__answer p:last-child {
	margin-bottom: 0;
}

/* The line under a price table: VAT, the euro rate the hryvnia column was
   converted at, and the date the price list is from. */
.sx-price-table__note {
	margin: 14px 0 0;
	max-width: 72ch;
	color: var( --sx-text-muted );
	font-size: 0.875rem;
	line-height: 1.55;
}

/*
 * The configurator button. Same weight as "Купити зараз" — it is still the
 * primary action — but without the trolley: nothing is being added to a cart
 * yet, and an icon promising that would be a small lie.
 */
.sx-product-hero__buy--calc::before {
	content: none;
}
