/* ==========================================================================
   TopShop — Сторінка товару (ТЗ §28)
   ========================================================================== */

/* --- Верхній блок: галерея | основне | купівля --------------------------- */

.ts-product__top {
	display: grid;
	/*
	 * minmax(0, 1fr), а не 1fr: інакше колонка не може бути вужчою за
	 * вміст, і фото 1746px від постачальника розтягувало сторінку —
	 * на телефоні з'являвся горизонтальний скрол. На десктопі нижче
	 * minmax уже стоїть, на мобільному його бракувало.
	 */
	grid-template-columns: minmax(0, 1fr);
	gap: var(--ts-space-6);
	margin-bottom: var(--ts-space-10);
}

@media (min-width: 900px) {
	.ts-product__top {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		gap: var(--ts-space-8);
	}

	/* Блок купівлі під галереєю, поки місця мало на три колонки */
	.ts-product__purchase {
		grid-column: 2;
	}
}

@media (min-width: 1200px) {
	/* 340px — щоб лічильник і "Додати в кошик" стали в один рядок */
	.ts-product__top {
		grid-template-columns: minmax(0, 5fr) minmax(0, 6fr) 340px;
	}

	.ts-product__purchase {
		grid-column: auto;
	}
}

/* --- Галерея ------------------------------------------------------------- */

.ts-gallery__stage {
	position: relative;
	/* Сцена не ширша за колонку, хоч би яке велике було фото. */
	min-width: 0;
	max-width: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 1 / 1;
	padding: var(--ts-space-4);
	background: var(--ts-color-surface);
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-lg);
	overflow: hidden;
}

.ts-gallery__image {
	width: 100%;
	height: 100%;
	object-fit: contain;
	mix-blend-mode: multiply;
}

/*
 * Бейджі в кутку сцени. Колонкою, а не рядком: назви різної довжини
 * («Безкоштовна доставка» проти «−12%»), у рядок вони розповзаються
 * на пів-фото.
 */
.ts-gallery__flags {
	position: absolute;
	top: var(--ts-space-3);
	left: var(--ts-space-3);
	z-index: var(--ts-z-base);
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--ts-space-1);
	max-width: calc(100% - var(--ts-space-6));
}

.ts-gallery__thumbs {
	display: flex;
	gap: var(--ts-space-2);
	margin-top: var(--ts-space-3);
	padding-bottom: var(--ts-space-1);
	/*
	 * Коли приховані мініатюри розкрито, їх стає більше за п'ять —
	 * тоді стрічка гортається, а не стискає фото до нерозбірливого.
	 */
	overflow-x: auto;
	scrollbar-width: thin;
}

/* --- Стрілки гортання --------------------------------------------------- */

.ts-gallery__nav {
	position: absolute;
	top: 50%;
	z-index: var(--ts-z-base);
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	margin-top: -18px;
	padding: 0;
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-full);
	background: var(--ts-color-surface);
	color: var(--ts-color-text-strong);
	cursor: pointer;
	/*
	 * Напівпрозорі, поки курсор не в галереї: стрілки не мають
	 * змагатися за увагу з фото товару.
	 */
	opacity: 0;
	transition: opacity var(--ts-duration-base) var(--ts-ease),
		background-color var(--ts-duration-base) var(--ts-ease);
}

.ts-product__gallery:hover .ts-gallery__nav,
.ts-gallery__nav:focus-visible {
	opacity: 1;
}

.ts-gallery__nav:hover {
	background: var(--ts-color-surface-hover);
}

.ts-gallery__nav--prev {
	left: var(--ts-space-3);
	transform: rotate(180deg);
}

.ts-gallery__nav--next {
	right: var(--ts-space-3);
}

/* На дотику наведення немає — показуємо завжди. */
@media (hover: none) {
	.ts-gallery__nav {
		opacity: 1;
	}
}

/* --- Лічильник прихованих мініатюр -------------------------------------- */

.ts-gallery__thumb.has-more {
	position: relative;
}

/*
 * Затемнення з «+N» поверх останньої видимої мініатюри. Клік по ньому
 * розкриває решту, а не перемикає фото.
 */
.ts-gallery__more {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: inherit;
	background: rgba(4, 22, 42, 0.62);
	color: #fff;
	font-size: var(--ts-text-sm);
	font-weight: var(--ts-weight-semibold);
}

.ts-gallery__thumb {
	/*
	 * Мініатюри ділять ширину галереї порівну, а не мають фіксовані
	 * 72px: п'ять штук із відступами не вміщалися в колонку, і
	 * лічильник «+N» опинявся за краєм видимої стрічки.
	 */
	flex: 1 1 0;
	min-width: 0;
	max-width: 78px;
	aspect-ratio: 1 / 1;
	height: auto;
	padding: var(--ts-space-1);
	background: var(--ts-color-surface);
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-md);
	overflow: hidden;
	transition: border-color var(--ts-duration-fast) var(--ts-ease);
}

.ts-gallery__thumb img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	mix-blend-mode: multiply;
}

.ts-gallery__thumb:hover {
	border-color: var(--ts-color-border-strong);
}

.ts-gallery__thumb.is-active {
	border-color: var(--ts-color-primary);
}

/* --- Основна колонка ----------------------------------------------------- */

.ts-product__brand {
	display: inline-block;
	margin-bottom: var(--ts-space-2);
	font-size: var(--ts-text-xs);
	font-weight: var(--ts-weight-semibold);
	letter-spacing: var(--ts-tracking-wide);
	text-transform: uppercase;
	color: var(--ts-color-muted);
}

/*
 * Бренд стоїть над блоком купівлі, притиснутий до правого краю
 * колонки — як у макеті. Там він читається як підпис до ціни, а не
 * як частина назви товару.
 */
.ts-product__brand {
	align-self: flex-end;
	text-align: right;
}

.ts-product__purchase {
	display: flex;
	flex-direction: column;
	gap: var(--ts-space-3);
}

/*
 * Обмежуємо і висоту, і ширину: логотипи приходять різних пропорцій,
 * і при вільній ширині витягнутий GIGABYTE займав 191px проти 121 в
 * ASUS — виглядав як інший рівень бренду, хоча це просто напис
 * довший. object-fit: contain вписує будь-яку пропорцію в рамку.
 */
.ts-product__brand-logo {
	display: block;
	width: auto;
	height: 26px;
	max-width: 130px;
	object-fit: contain;
	object-position: right center;
	/*
	 * Логотипи приходять різної насиченості: приглушуємо, щоб вони не
	 * сперечалися з назвою товару, і повертаємо повний колір при
	 * наведенні — так видно, що це посилання.
	 */
	opacity: 0.72;
	transition: opacity var(--ts-duration-base) var(--ts-ease);
}

.ts-product__brand:hover .ts-product__brand-logo {
	opacity: 1;
}

.ts-product__brand:hover {
	color: var(--ts-color-primary);
	text-decoration: none;
}

/*
 * Назви товарів довгі — «Відеокарта MSI GeForce RTX5090 32GB GAMING
 * TRIO OC (RTX 5090 32G GAMING TRIO OC)» на 32px займала три рядки
 * й відсувала ціну з блоком купівлі за межі екрана. 24px вистачає,
 * щоб заголовок лишався головним, і вміщає назву у два рядки.
 */
.ts-product__title {
	margin-bottom: var(--ts-space-3);
	font-size: 1.25rem; /* 20px */
	line-height: var(--ts-leading-snug);
}

@media (min-width: 600px) {
	.ts-product__title {
		font-size: 1.375rem; /* 22px */
	}
}

@media (min-width: 900px) {
	.ts-product__title {
		font-size: 1.5rem; /* 24px */
	}
}

/*
 * Код і Part Number помітніші за звичайний дрібний підпис: у цій
 * категорії за ними звіряють сумісність і шукають у постачальника,
 * тож це одні з найважливіших даних на сторінці. Але без крику —
 * підкладка й моноширинний шрифт, а не колір чи великий кегль.
 */
/*
 * Код і Part Number у стовпчик, як у макеті: так вони читаються як
 * пара «підпис — значення», а не як два однакові чипи в рядок.
 */
/*
 * Коди в рядок: їх щонайбільше два, і разом вони коротші за назву
 * товару. Окремими рядками вони займали висоту, не додаючи ясності.
 * flex-wrap лишаємо — на вузькому екрані довгий part number
 * переноситься замість того, щоб розпирати колонку.
 */
.ts-product__codes {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--ts-space-2) var(--ts-space-5);
	margin-bottom: var(--ts-space-4);
	font-size: var(--ts-text-sm);
	color: var(--ts-color-text);
}

/*
 * Без підкладки: сіра плашка робила з коду елемент інтерфейсу, хоча
 * це просто дані, які звіряють очима й копіюють. Читабельність дає
 * темний моноширинний текст, а не рамка.
 */
.ts-product__code {
	display: inline-flex;
	align-items: center;
	gap: var(--ts-space-1);
}

.ts-product__code .ts-mono {
	color: var(--ts-color-text-strong);
	font-weight: var(--ts-weight-medium);
	letter-spacing: 0.01em;
}

/*
 * Підпис теж темний: це не службова дрібниця, а частина того, що
 * покупець диктує менеджеру по телефону. Світло-сірий на білому
 * читався гірше за сам код і плутав, де закінчується підпис.
 */
.ts-product__code-label {
	color: var(--ts-color-muted);
}

/* --- Лінійка: той самий товар в інших об'ємах ----------------------------- */

/*
 * Це окремі товари з власними адресами, а не варіації: клік веде на
 * іншу сторінку. Тому плашки — посилання, а поточний варіант не
 * клікабельний і виглядає як обраний.
 */
.ts-family {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: var(--ts-space-2) var(--ts-space-3);
	margin-bottom: var(--ts-space-5);
	padding: var(--ts-space-3) var(--ts-space-4);
	background: var(--ts-color-surface-sunken);
	border-radius: var(--ts-radius-md);
}

.ts-family__label {
	font-size: var(--ts-text-sm);
	color: var(--ts-color-muted);
}

.ts-family__items {
	display: flex;
	flex-wrap: wrap;
	gap: var(--ts-space-2);
}

.ts-family__item {
	display: inline-flex;
	align-items: center;
	/* 36px по висоті: на телефоні в це ще зручно влучати пальцем. */
	min-height: 36px;
	padding: 0 var(--ts-space-3);
	font-size: var(--ts-text-sm);
	font-weight: var(--ts-weight-medium);
	color: var(--ts-color-text);
	background: var(--ts-color-surface);
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-sm);
	white-space: nowrap;
}

/* Відмітка редакції: «/EU» поруч з об'ємом, дрібним і приглушеним. */
.ts-family__suffix {
	margin-left: 4px;
	font-size: var(--ts-text-2xs);
	font-weight: var(--ts-weight-normal);
	color: var(--ts-color-faint);
}

a.ts-family__item:hover {
	color: var(--ts-color-primary);
	border-color: var(--ts-color-primary);
	text-decoration: none;
}

.ts-family__item.is-current {
	color: var(--ts-color-primary);
	border-color: var(--ts-color-primary);
	background: var(--ts-color-primary-soft);
	cursor: default;
}

/* --- Ключові характеристики ---------------------------------------------- */

.ts-product__keyspecs .ts-label {
	margin-bottom: var(--ts-space-3);
}

/*
 * Характеристики парами з іконкою: шість рядків поспіль зливаються в
 * суцільний текст, а двома колонками з піктограмою око знаходить
 * потрібне одразу.
 */
.ts-keyspecs {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--ts-space-3) var(--ts-space-5);
	margin: 0;
}

@media (min-width: 560px) {
	.ts-keyspecs {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.ts-keyspecs__row {
	display: flex;
	align-items: flex-start;
	gap: var(--ts-space-2);
	min-width: 0;
	font-size: var(--ts-text-sm);
}

.ts-keyspecs__icon {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* Без плашки, як у макеті: іконка лише позначає рядок. */
	color: var(--ts-color-primary);
}

.ts-keyspecs__text {
	min-width: 0;
}

.ts-keyspecs__label {
	color: var(--ts-color-muted);
	font-size: var(--ts-text-xs);
	line-height: 1.3;
}

.ts-keyspecs__value {
	margin: 0;
	color: var(--ts-color-text-strong);
	font-weight: var(--ts-weight-medium);
	line-height: 1.35;
	/* Довгі перерахування не мають розпирати колонку. */
	overflow-wrap: anywhere;
}

/* --- Рейтинг ------------------------------------------------------------ */

/*
 * Рейтинг під назвою — те, на що дивляться одразу після ціни, тому
 * розмір основного тексту, а не дрібний: на 13px і «5.0», і кількість
 * відгуків читались як службова примітка.
 */
.ts-product__rating {
	display: flex;
	align-items: center;
	gap: var(--ts-space-2);
	margin-bottom: var(--ts-space-3);
	font-size: var(--ts-text-base);
}

.ts-stars {
	display: inline-flex;
	gap: 1px;
}

.ts-stars__item {
	display: inline-flex;
	color: var(--ts-color-border-strong);
}

.ts-stars__item .ts-icon {
	fill: currentColor;
	stroke: none;
}

.ts-stars__item.is-on {
	color: #f5a524;
}

.ts-product__rating-value {
	font-size: var(--ts-text-md);
	font-weight: var(--ts-weight-bold);
	color: var(--ts-color-text-strong);
}

.ts-product__rating-count {
	color: var(--ts-color-muted);
}

.ts-product__rating-count:hover {
	color: var(--ts-color-primary);
}

/*
 * Поки відгуків немає — запрошення замість зірок. Місце в макеті те
 * саме, тож поява першого відгуку не зсуває сторінку.
 */
.ts-product__rating-empty {
	display: inline-flex;
	align-items: center;
	gap: var(--ts-space-1);
	color: var(--ts-color-muted);
}

.ts-product__rating-empty:hover {
	color: var(--ts-color-primary);
	text-decoration: none;
}

/* --- Кнопка копіювання -------------------------------------------------- */

.ts-copy {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	margin-left: 2px;
	padding: 0;
	border: 0;
	border-radius: var(--ts-radius-sm);
	background: transparent;
	color: var(--ts-color-muted);
	cursor: pointer;
	vertical-align: middle;
	transition: color var(--ts-duration-base) var(--ts-ease),
		background-color var(--ts-duration-base) var(--ts-ease);
}

.ts-copy:hover {
	background: var(--ts-color-surface-sunken);
	color: var(--ts-color-primary);
}

/* Підтвердження: галочка на мить замість іконки. */
.ts-copy.is-done {
	color: var(--ts-color-success, #008a20);
}

.ts-copy.is-done .ts-icon {
	display: none;
}

.ts-copy.is-done::after {
	content: "✓";
	font-size: 13px;
	line-height: 1;
}

/*
 * Підказка «Скопійовано» поруч із кнопкою.
 *
 * Сама галочка не каже, що саме сталося: її однаково можна прочитати
 * як «код правильний». Слово знімає це питання.
 *
 * Текст беремо з data-атрибута, щоб не тримати переклад у CSS.
 */
/*
 * Ставимо підказку над кнопкою, а не збоку: коди тепер в один рядок,
 * і збоку вона лягала просто на сусідній «Part Number».
 */
.ts-copy.is-done::before {
	content: attr(data-copied-label);
	position: absolute;
	bottom: calc(100% + 4px);
	left: 50%;
	transform: translateX(-50%);
	padding: 3px var(--ts-space-2);
	font-family: var(--ts-font-sans);
	font-size: var(--ts-text-2xs);
	font-weight: var(--ts-weight-medium);
	line-height: 1.4;
	white-space: nowrap;
	color: var(--ts-color-surface);
	background: var(--ts-color-text-strong);
	border-radius: var(--ts-radius-sm);
	pointer-events: none;
	z-index: 2;
}

.ts-product__specs-link {
	display: inline-flex;
	align-items: center;
	gap: var(--ts-space-1);
	margin-top: var(--ts-space-3);
	font-size: var(--ts-text-sm);
	font-weight: var(--ts-weight-medium);
}

/* --- Блок купівлі -------------------------------------------------------- */

.ts-buybox {
	padding: var(--ts-space-5);
	background: var(--ts-color-surface);
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-lg);
	box-shadow: var(--ts-shadow-sm);
}

/*
 * Липкий на широких екранах: ціна і CTA лишаються на очах, поки
 * користувач гортає характеристики. На вузьких — звичайний блок,
 * інакше він з'їдає висоту екрана.
 */
@media (min-width: 1200px) {
	.ts-product__purchase {
		position: sticky;
		top: calc(var(--ts-header-height) + var(--ts-space-4));
	}
}

.ts-buybox__price {
	margin-bottom: var(--ts-space-2);
}

.ts-buybox__saving {
	margin-bottom: var(--ts-space-3);
	font-size: var(--ts-text-sm);
	font-weight: var(--ts-weight-medium);
	color: var(--ts-color-discount);
}

.ts-buybox__stock {
	margin-bottom: var(--ts-space-4);
	padding-bottom: var(--ts-space-4);
	border-bottom: 1px solid var(--ts-color-border);
}

/*
 * Кількість і кнопка в один рядок лише коли кнопці вистачає місця.
 * У вузькій колонці 320px "Додати в кошик" розривалось на три рядки,
 * тому там кнопка йде під лічильником на всю ширину.
 */
.ts-buybox__row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--ts-space-3);
	margin-bottom: var(--ts-space-3);
}

/*
 * flex-basis 140px: кнопка має вміститись поруч із лічильником
 * у колонці 298px (лічильник ~128px + відступ 12px). При більшому
 * значенні вона переносилась на окремий рядок.
 */
/*
 * Висота 44px у всього рядка: лічильник, кнопка кошика і «Швидке
 * замовлення» під ними мають збігатися, інакше блок виглядає
 * зібраним нашвидкуруч. Клас --lg тут не використовуємо саме тому:
 * він задає 52px.
 */
.ts-buybox__submit {
	flex: 1 1 140px;
	min-width: 0;
	white-space: nowrap;
	min-height: 44px;
	padding-block: var(--ts-space-2);
	/*
	 * 14px, як у «Швидкого замовлення» під нею: при 16px текст
	 * «Додати в кошик» потребував 177px у кнопці на 156px і
	 * видавлював бічні відступи. Дві кнопки поруч мають читатись як
	 * пара, а не як різні за вагою елементи.
	 */
	font-size: var(--ts-text-base);
	/* Бічні відступи менші: колонка вузька, кожен піксель на рахунку. */
	padding-inline: var(--ts-space-4);
}

/* Іконка не має стискатися, коли тексту забагато для колонки. */
.ts-buybox__submit .ts-icon,
.ts-buybox__quick .ts-icon {
	flex: 0 0 auto;
}

.ts-buybox__inquiry {
	margin-bottom: var(--ts-space-4);
}

.ts-buybox__unavailable {
	margin-bottom: var(--ts-space-3);
	padding: var(--ts-space-3);
	background: var(--ts-color-surface-sunken);
	border-radius: var(--ts-radius-md);
	font-size: var(--ts-text-sm);
	color: var(--ts-color-muted);
	text-align: center;
}

.ts-buybox__perks {
	display: flex;
	flex-direction: column;
	gap: var(--ts-space-2);
	padding-top: var(--ts-space-4);
	border-top: 1px solid var(--ts-color-border);
}

.ts-buybox__perk {
	display: flex;
	align-items: flex-start;
	gap: var(--ts-space-3);
	font-size: var(--ts-text-base);
	color: var(--ts-color-muted);
}

/*
 * Без підкладки: плашка робила з іконки кнопку, хоча це підпис.
 * Синій колір і так відділяє її від тексту.
 */
.ts-buybox__perk-icon {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--ts-color-primary);
}

.ts-buybox__perk-text {
	display: flex;
	flex-direction: column;
	min-width: 0;
	gap: 1px;
}

.ts-buybox__perk-title {
	color: var(--ts-color-text-strong);
	font-weight: var(--ts-weight-medium);
	font-size: var(--ts-text-md);
	line-height: 1.3;
}

.ts-buybox__perk-note {
	font-size: var(--ts-text-sm);
	color: var(--ts-color-faint);
	line-height: 1.35;
}

/* --- Обране і порівняння ------------------------------------------------ */

/*
 * Дві тихі дії в рядок: вони третього рівня після кошика й швидкого
 * замовлення, тож не мають виглядати ще двома кнопками.
 */
.ts-buybox__actions {
	display: flex;
	align-items: center;
	gap: var(--ts-space-2);
	margin-top: var(--ts-space-3);
	padding-bottom: var(--ts-space-4);
	border-bottom: 1px solid var(--ts-color-border);
}

/*
 * По половині ширини кожна: так вони читаються як пара рівноправних
 * дій, а не як текст, що випадково опинився поруч.
 *
 * Розмір такий самий, як у переваг нижче: це теж дії з товаром, а
 * дрібним шрифтом вони виглядали як примітка під кнопкою купівлі.
 * 44px висоти — мінімальна зручна ціль на дотик.
 */
.ts-buybox__action {
	flex: 1 1 50%;
	min-width: 0;
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--ts-space-2);
	padding: var(--ts-space-2) var(--ts-space-1);
	border: 0;
	background: none;
	color: var(--ts-color-text-strong);
	font-size: var(--ts-text-md);
	font-weight: var(--ts-weight-medium);
	cursor: pointer;
	transition: color var(--ts-duration-base) var(--ts-ease);
}

/* Іконка більша й синя — як у переваг, щоб пара читалась як одне ціле. */
.ts-buybox__action .ts-icon {
	flex: 0 0 auto;
	color: var(--ts-color-primary);
	transition: color var(--ts-duration-base) var(--ts-ease);
}

.ts-buybox__action:hover:not(:disabled) .ts-icon {
	color: inherit;
}

.ts-buybox__action:hover:not(:disabled) {
	color: var(--ts-color-primary);
}

.ts-buybox__action:disabled {
	opacity: 0.45;
	cursor: not-allowed;
}

.ts-buybox__action.is-on {
	color: var(--ts-color-danger, #d63638);
}

/*
 * Заповнене серце позначає, що товар уже в списку. Колір перебиває
 * синій за замовчуванням: у цьому стані іконка має бути тим самим
 * червоним, що й підпис.
 */
.ts-buybox__action.is-on .ts-icon {
	color: inherit;
	fill: currentColor;
}

/*
 * Правило лишилося від часів, коли перевагами були зелені галочки.
 * Тепер це піктограми теми — синій акцент, як у решти інтерфейсу.
 */
.ts-buybox__perk svg {
	flex: none;
	margin-top: 1px;
	color: var(--ts-color-primary);
}

/* --- Кількість ----------------------------------------------------------- */

/*
 * inline-flex, а не flex: як блоковий елемент лічильник розтягувався
 * на всю ширину колонки-батька (у кошику це 140px при вмісті 121px),
 * і праворуч від "+" лишалася порожнеча.
 */
.ts-qty {
	display: inline-flex;
	align-items: center;
	flex: none;
	width: fit-content;
	border: 1px solid var(--ts-color-border-strong);
	border-radius: var(--ts-radius-md);
	overflow: hidden;
}

/*
 * 44px — мінімальна зручна ціль дотику і водночас висота кнопки
 * «Швидке замовлення» поруч: рядок купівлі має бути однієї висоти,
 * інакше блок виглядає зібраним нашвидкуруч.
 */
.ts-qty__btn {
	display: flex;
	align-items: center;
	justify-content: center;
	/*
	 * 34px замість 40: лічильник ділить рядок із кнопкою кошика в
	 * колонці 298px, і кожен зайвий піксель тут забирає місце в
	 * напису «Додати в кошик». 34 + 34 + 40 = 108 лишає кнопці 178.
	 */
	width: 34px;
	height: 42px;
	font-size: var(--ts-text-lg);
	color: var(--ts-color-muted);
	transition: background-color var(--ts-duration-fast) var(--ts-ease);
}

.ts-qty__btn:hover {
	background: var(--ts-color-surface-sunken);
	color: var(--ts-color-text);
}

.ts-qty__input {
	/* Кількість рідко буває більшою за два знаки. */
	width: 40px;
	/* 42 + 2px рамки контейнера = рівно 44, як у сусідніх кнопок. */
	height: 42px;
	padding: 0;
	border: 0;
	border-inline: 1px solid var(--ts-color-border);
	text-align: center;
	font-size: var(--ts-text-base);
	font-weight: var(--ts-weight-semibold);
	/* Стрілки number-інпута тут зайві: є власні кнопки */
	appearance: textfield;
	-moz-appearance: textfield;
}

.ts-qty__input::-webkit-outer-spin-button,
.ts-qty__input::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.ts-qty__input:focus {
	outline: none;
	box-shadow: inset 0 0 0 2px var(--ts-color-primary);
}

/* --- Нижня частина: характеристики, опис --------------------------------- */

.ts-product__details {
	max-width: 900px;
}

.ts-section__title {
	margin-bottom: var(--ts-space-4);
	font-size: var(--ts-text-xl);
}

.ts-specs {
	width: 100%;
	font-size: var(--ts-text-sm);
}

.ts-specs__row:nth-child(odd) {
	background: var(--ts-color-surface-sunken);
}

.ts-specs__label,
.ts-specs__value {
	padding: var(--ts-space-3);
	text-align: left;
	vertical-align: top;
}

.ts-specs__label {
	width: 45%;
	font-weight: var(--ts-weight-regular);
	color: var(--ts-color-muted);
}

.ts-specs__value {
	font-weight: var(--ts-weight-medium);
	color: var(--ts-color-text);
}

@media (max-width: 559px) {
	.ts-specs__label {
		width: 50%;
	}
}

/* --- Інфоблоки: гарантія, доставка --------------------------------------- */

.ts-product__info-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: var(--ts-space-4);
	margin-block: var(--ts-space-10);
}

.ts-infobox {
	padding: var(--ts-space-5);
	background: var(--ts-color-surface-sunken);
	border-radius: var(--ts-radius-lg);
}

.ts-infobox__title {
	margin-bottom: var(--ts-space-2);
	font-size: var(--ts-text-md);
	font-weight: var(--ts-weight-semibold);
	color: var(--ts-color-text-strong);
}

.ts-infobox__text {
	font-size: var(--ts-text-sm);
	line-height: var(--ts-leading-relaxed);
	color: var(--ts-color-muted);
}

/* --- Модалка ------------------------------------------------------------- */

.ts-modal {
	position: fixed;
	inset: 0;
	z-index: var(--ts-z-modal);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--ts-space-4);
}

.ts-modal[hidden] {
	display: none;
}

.ts-modal__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(4, 22, 42, 0.5);
}

.ts-modal__dialog {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: 440px;
	max-height: calc(100vh - var(--ts-space-8));
	display: flex;
	flex-direction: column;
	background: var(--ts-color-surface);
	border-radius: var(--ts-radius-xl);
	box-shadow: var(--ts-shadow-lg);
	overflow: hidden;
}

.ts-modal__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ts-space-3);
	padding: var(--ts-space-4) var(--ts-space-5);
	border-bottom: 1px solid var(--ts-color-border);
	flex: none;
}

.ts-modal__title {
	font-size: var(--ts-text-lg);
	font-weight: var(--ts-weight-semibold);
	color: var(--ts-color-text-strong);
}

.ts-modal__close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	flex: none;
	border-radius: var(--ts-radius-md);
	color: var(--ts-color-muted);
}

.ts-modal__close:hover {
	background: var(--ts-color-surface-sunken);
	color: var(--ts-color-text);
}

.ts-modal__body {
	padding: var(--ts-space-5);
	overflow-y: auto;
}

.ts-modal__product {
	margin-bottom: var(--ts-space-4);
	padding: var(--ts-space-3);
	background: var(--ts-color-surface-sunken);
	border-radius: var(--ts-radius-md);
	font-size: var(--ts-text-sm);
	font-weight: var(--ts-weight-medium);
	color: var(--ts-color-text);
}

/* --- Форма запиту -------------------------------------------------------- */

.ts-inquiry {
	display: flex;
	flex-direction: column;
	gap: var(--ts-space-4);
}

/*
 * Після успіху JS ставить формі hidden. Це атрибут, а його display:none
 * слабший за правило з класом вище — без цього форма лишалась на місці,
 * а подяка з'їжджала під неї.
 */
.ts-inquiry[hidden] {
	display: none;
}

.ts-required {
	color: var(--ts-color-danger);
}

.ts-inquiry__note {
	font-size: var(--ts-text-xs);
	color: var(--ts-color-faint);
	text-align: center;
}

.ts-inquiry__success {
	padding-block: var(--ts-space-6);
	text-align: center;
	color: var(--ts-color-muted);
}

.ts-inquiry__success-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	margin-bottom: var(--ts-space-4);
	background: var(--ts-color-primary-soft);
	border-radius: var(--ts-radius-full);
	color: var(--ts-color-primary);
}

.ts-inquiry__success-title {
	margin-bottom: var(--ts-space-2);
	font-size: var(--ts-text-lg);
	font-weight: var(--ts-weight-semibold);
	color: var(--ts-color-text-strong);
}

/* Поки запит виконується — не даємо натиснути двічі */
.ts-inquiry.is-loading {
	opacity: 0.6;
	pointer-events: none;
}

/* --- Липка панель купівлі (мобільне) --------------------------------------- */

.ts-sticky-buy {
	position: fixed;
	z-index: var(--ts-z-sticky);
	right: 0;
	bottom: 0;
	left: 0;
	background: var(--ts-color-surface);
	border-top: 1px solid var(--ts-color-border);
	box-shadow: var(--ts-shadow-lg);
	/* Щоб панель не лізла під домашню смугу iPhone. */
	padding-bottom: env(safe-area-inset-bottom);
	transform: translateY(100%);
	transition: transform var(--ts-duration-fast) var(--ts-ease);
}

.ts-sticky-buy[hidden] {
	display: none;
}

.ts-sticky-buy.is-visible {
	transform: translateY(0);
}

.ts-sticky-buy__inner {
	display: flex;
	align-items: center;
	gap: var(--ts-space-3);
	padding: var(--ts-space-3) var(--ts-space-4);
}

.ts-sticky-buy__info {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	min-width: 0;
}

.ts-sticky-buy__name {
	overflow: hidden;
	font-size: var(--ts-text-xs);
	line-height: var(--ts-leading-snug);
	color: var(--ts-color-muted);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ts-sticky-buy__price {
	font-size: var(--ts-text-md);
	font-weight: var(--ts-weight-bold);
	color: var(--ts-color-text-strong);
}

.ts-sticky-buy__submit {
	flex: 0 0 auto;
	/* 44px — мінімальна зручна ціль для пальця. */
	min-height: 48px;
}

/* На десктопі липким лишається сам блок купівлі — панель не потрібна. */
@media (min-width: 1024px) {
	.ts-sticky-buy {
		display: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.ts-sticky-buy {
		transition: none;
	}
}

/* --- Вкладки сторінки товару -------------------------------------------- */

/*
 * Панель показуємо лише на десктопі. На мобільному секції йдуть одна
 * під одною: вкладка ховає вміст за зайвий тап, а характеристики —
 * головне, заради чого сюди приходять.
 */
.ts-tabs {
	display: none;
}

.is-hidden-tab {
	display: none;
}

@media (min-width: 900px) {
	.ts-tabs {
		display: flex;
		gap: var(--ts-space-6);
		margin-bottom: var(--ts-space-6);
		border-bottom: 1px solid var(--ts-color-border);
		overflow-x: auto;
		scrollbar-width: none;
	}

	.ts-tabs::-webkit-scrollbar {
		display: none;
	}

	.ts-tabs__item {
		position: relative;
		flex: none;
		padding-bottom: var(--ts-space-3);
		font-size: var(--ts-text-base);
		font-weight: var(--ts-weight-medium);
		color: var(--ts-color-muted);
		white-space: nowrap;
	}

	.ts-tabs__item:hover {
		color: var(--ts-color-text-strong);
		text-decoration: none;
	}

	.ts-tabs__item.is-active {
		color: var(--ts-color-text-strong);
	}

	/* Підкреслення активної — на межі панелі, а не під текстом. */
	.ts-tabs__item.is-active::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		bottom: -1px;
		height: 2px;
		background: var(--ts-color-primary);
		border-radius: 2px 2px 0 0;
	}

	/*
	 * Заголовки секцій усередині вкладки зайві: назва вкладки вже
	 * сказала, що це. На мобільному вони лишаються.
	 */
	.ts-product__details .ts-section__title {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}
}

/* --- Швидке замовлення й обране ----------------------------------------- */

.ts-buybox__quick {
	margin-top: var(--ts-space-2);
}

/*
 * Обране — тиха дія текстом: у макеті вона третього рівня, поруч із
 * двома кнопками. Робити її ще однією кнопкою означало б три однакові
 * прямокутники поспіль.
 */
.ts-buybox__wish {
	display: inline-flex;
	align-items: center;
	gap: var(--ts-space-2);
	margin-top: var(--ts-space-3);
	padding: var(--ts-space-1) 0;
	border: 0;
	background: none;
	color: var(--ts-color-muted);
	font-size: var(--ts-text-sm);
	cursor: pointer;
	transition: color var(--ts-duration-base) var(--ts-ease);
}

.ts-buybox__wish:hover {
	color: var(--ts-color-primary);
}

.ts-buybox__wish.is-on {
	color: var(--ts-color-danger, #d63638);
}

/* Заповнене серце позначає, що товар уже в списку. */
.ts-buybox__wish.is-on .ts-icon {
	fill: currentColor;
}

/* --- Відгуки ------------------------------------------------------------ */

/*
 * Білий фон, як у решти карток: сіра підкладка відсувала підсумок
 * на другий план, хоча це перше, що дивляться у відгуках.
 * Межу тримає рамка.
 */
.ts-reviews__summary {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--ts-space-5);
	margin-bottom: var(--ts-space-5);
	padding: var(--ts-space-5);
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-lg);
	background: var(--ts-color-surface);
}

@media (min-width: 720px) {
	.ts-reviews__summary {
		grid-template-columns: auto minmax(0, 1fr);
		gap: var(--ts-space-8);
		align-items: center;
	}
}

.ts-reviews__score {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--ts-space-1);
}

.ts-reviews__score-value {
	font-size: var(--ts-text-3xl);
	font-weight: var(--ts-weight-bold);
	line-height: 1;
	color: var(--ts-color-text-strong);
}

.ts-reviews__score-count {
	font-size: var(--ts-text-sm);
	color: var(--ts-color-muted);
}

/*
 * Розподіл оцінок: покупцю він корисніший за саме середнє — видно,
 * чи 4.5 зібралось із рівних четвірок, чи з п'ятірок і однієї одиниці.
 */
.ts-reviews__spread {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.ts-reviews__spread-row {
	display: flex;
	align-items: center;
	gap: var(--ts-space-2);
	font-size: var(--ts-text-xs);
	color: var(--ts-color-muted);
}

.ts-reviews__spread-row .ts-icon {
	color: #f5a524;
	fill: currentColor;
	stroke: none;
}

.ts-reviews__spread-bar {
	flex: 1 1 auto;
	height: 6px;
	border-radius: var(--ts-radius-full);
	background: var(--ts-color-border);
	overflow: hidden;
}

.ts-reviews__spread-bar > span {
	display: block;
	height: 100%;
	background: #f5a524;
}

.ts-reviews__spread-count {
	min-width: 24px;
	text-align: right;
}

.ts-reviews__list {
	display: flex;
	flex-direction: column;
	gap: var(--ts-space-3);
	margin: 0 0 var(--ts-space-5);
	padding: 0;
	list-style: none;
}

/*
 * Кожен відгук — картка з рамкою, а не рядок із лінією знизу.
 * Лінія в останнього відгуку прибиралась, тож при одному відгуку —
 * а це найчастіший випадок на старті — не було видно нічого, і текст
 * висів у порожнечі.
 *
 * Клас саме ts-review-card: .ts-review вже зайнятий підсумком
 * замовлення на чекауті, а _cart.css підключається після цього файлу
 * й перебивав би тутешні правила.
 */
.ts-review-card {
	padding: var(--ts-space-4);
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-lg);
	background: var(--ts-color-surface);
}

.ts-review__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--ts-space-3);
	margin-bottom: var(--ts-space-2);
}

.ts-review__author {
	font-weight: var(--ts-weight-semibold);
	color: var(--ts-color-text-strong);
}

.ts-review__verified {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-size: var(--ts-text-xs);
	color: #08703a;
}

.ts-review__date {
	margin-left: auto;
	font-size: var(--ts-text-xs);
	color: var(--ts-color-faint);
}

.ts-review__text {
	color: var(--ts-color-text);
	line-height: var(--ts-leading-relaxed);
}

.ts-review__text p:last-child {
	margin-bottom: 0;
}

.ts-reviews__empty,
.ts-reviews__note {
	margin-bottom: var(--ts-space-5);
	color: var(--ts-color-muted);
}

/* --- Форма відгуку ------------------------------------------------------ */

.ts-review-form,
.ts-reviews__login {
	padding: var(--ts-space-5);
	border: 1px solid var(--ts-color-border);
	border-radius: var(--ts-radius-lg);
	background: var(--ts-color-surface);
}

.ts-review-form__title {
	margin: 0 0 var(--ts-space-4);
	font-size: var(--ts-text-lg);
	color: var(--ts-color-text-strong);
}

.ts-review-form__note {
	margin: var(--ts-space-3) 0 0;
	font-size: var(--ts-text-xs);
	color: var(--ts-color-faint);
}

.ts-reviews__login p {
	margin: 0 0 var(--ts-space-3);
	color: var(--ts-color-muted);
}

/*
 * Зірки-радіо. Порядок у розмітці зворотний (5→1), тому підсвічуємо
 * саму зірку і всі наступні в DOM — це й є «ця та лівіші» на екрані.
 */
.ts-rating-input {
	display: inline-flex;
	flex-direction: row-reverse;
	justify-content: flex-end;
	gap: 2px;
}

.ts-rating-input input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
}

.ts-rating-input label {
	display: inline-flex;
	padding: 2px;
	color: var(--ts-color-border-strong);
	cursor: pointer;
	transition: color var(--ts-duration-fast) var(--ts-ease);
}

.ts-rating-input label .ts-icon {
	fill: currentColor;
	stroke: none;
}

.ts-rating-input input:checked ~ label,
.ts-rating-input label:hover,
.ts-rating-input label:hover ~ label {
	color: #f5a524;
}

/* Обведення для клавіатури: інакше вибір оцінки з Tab невидимий. */
.ts-rating-input input:focus-visible + label {
	outline: 2px solid var(--ts-color-primary);
	outline-offset: 2px;
	border-radius: var(--ts-radius-sm);
}

/* --- Подяка після відправки відгуку ------------------------------------- */

.ts-review-sent {
	display: flex;
	align-items: flex-start;
	gap: var(--ts-space-3);
	margin-bottom: var(--ts-space-5);
	padding: var(--ts-space-4);
	border: 1px solid #b7e3c6;
	border-radius: var(--ts-radius-lg);
	background: #e7f6ec;
}

.ts-review-sent__icon {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border-radius: var(--ts-radius-full);
	background: #08703a;
	color: #fff;
}

.ts-review-sent__title {
	margin: 0 0 2px;
	font-weight: var(--ts-weight-semibold);
	color: #08703a;
}

.ts-review-sent__text {
	margin: 0;
	font-size: var(--ts-text-sm);
	color: var(--ts-color-text);
}

/* --- Лупа в галереї ------------------------------------------------------ */

/*
 * Кругла лінза, що йде за курсором і показує збільшену ділянку фото.
 * Її розміри й фон задає JS; тут — вигляд і поведінка.
 */
.ts-gallery__lens {
	position: absolute;
	/* Центр лінзи — під курсором, тому зсуваємо на пів-розміру. */
	transform: translate(-50%, -50%);
	width: 180px;
	height: 180px;
	pointer-events: none;
	opacity: 0;
	visibility: hidden;
	border-radius: var(--ts-radius-full);
	border: 2px solid rgba(255, 255, 255, 0.9);
	box-shadow: var(--ts-shadow-lg), 0 0 0 1px var(--ts-color-border);
	background-color: #fff;
	background-repeat: no-repeat;
	/*
	 * Згладжування, а не різкі пікселі: у постачальника фото 400×400,
	 * і при збільшенні браузер має розмити перехід, інакше видно
	 * «драбинку». На великих фото це нічого не псує.
	 */
	image-rendering: auto;
	transition: opacity var(--ts-duration-fast) var(--ts-ease);
	z-index: var(--ts-z-base);
}

.ts-gallery__lens.is-visible {
	opacity: 1;
	visibility: visible;
}

/* Курсор-приціл підказує, що фото можна роздивитись. */
.ts-gallery__stage.has-zoom {
	cursor: zoom-in;
}

/*
 * Дотик: лупи немає. Пальцем неможливо «навести», а сама лінза
 * перекривала б фото — на телефоні працює звичайне гортання.
 */
@media (hover: none), (pointer: coarse) {
	.ts-gallery__lens {
		display: none;
	}

	.ts-gallery__stage.has-zoom {
		cursor: default;
	}
}
