/* ── Design tokens ──────────────────────────────────────────────────────────
   Единственный источник цветов — Telegram Theme Params.
   Fallback-значения для браузерного dev-режима (светлая тема).
   Никакого хардкода цветов за пределами этого блока.
   ─────────────────────────────────────────────────────────────────────────── */
:root {
  /* Поверхности */
  --bg:          var(--tg-theme-bg-color, #efeff3);
  --surface:     var(--tg-theme-section-bg-color, #ffffff);
  --surface2:    var(--tg-theme-secondary-bg-color, #f1f1f1);

  /* Текст */
  --text-primary:   var(--tg-theme-text-color, #000000);
  --text-secondary: var(--tg-theme-subtitle-text-color, var(--tg-theme-hint-color, #6d6d72));
  --text-hint:      var(--tg-theme-hint-color, #8e8e93);

  /* Акцент */
  --accent:      var(--tg-theme-button-color, #007aff);
  --accent-text: var(--tg-theme-button-text-color, #ffffff);
  --link:        var(--tg-theme-link-color, #007aff);

  /* Системные */
  --destructive: var(--tg-theme-destructive-text-color, #ff3b30);
  --divider:     color-mix(in srgb, var(--text-primary) 12%, transparent);

  /* Типографика: 3 размера, 2 веса */
  --text-sm:  13px;
  --text-md:  15px;
  --text-lg:  17px;
  --fw-normal: 400;
  --fw-semi:   600;

  /* Отступы: кратны 4 */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-6: 24px;

  /* Радиусы */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;

  /* Touch target */
  --touch: 44px;
}

/* ── Reset ──────────────────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: var(--text-md);
  line-height: 1.4;
  color: var(--text-primary);
  background: var(--bg);
  min-height: 100vh;
  /* env(safe-area-inset-*) везде в этом файле резолвится в 0, пока
     <meta viewport> не содержит viewport-fit=cover (layout.templ) —
     без него страница не "заявляет" о готовности рисовать под вырезом/
     Dynamic Island, и спецификация отдаёт инсеты нулевыми. */
  padding-bottom: calc(80px + env(safe-area-inset-bottom));
  -webkit-tap-highlight-color: transparent;
}

@keyframes bumpAnim {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.3); }
  100% { transform: scale(1); }
}

@keyframes heartPulse {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.35); }
  60%  { transform: scale(0.92); }
  100% { transform: scale(1); }
}

/* ── Product grid ────────────────────────────────────────────────────────── */
.product-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-3);
  padding: var(--sp-4);
}

/* ── Product card ────────────────────────────────────────────────────────── */
.product-card {
  position: relative;
  background: var(--surface);
  border-radius: var(--r-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--divider);
}

/* ── Wishlist heart toggle ───────────────────────────────────────────────── */
.wishlist-toggle {
  position: absolute;
  top: var(--sp-2);
  right: var(--sp-2);
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: #fff;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  -webkit-tap-highlight-color: transparent;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
}

.wishlist-toggle--active {
  color: #e0245e;
}

.wishlist-toggle--active svg {
  fill: currentColor;
}

.wishlist-toggle--pulse svg {
  animation: heartPulse 0.35s ease;
}

/* На деталке кнопка сидит на белой карточке, а не на фото товара — базовый
   белый цвет (для контраста с фото в каталоге) здесь был бы невидим, поэтому
   не наследуем ни его, ни фоновый круг/тень, задуманные только для карточки. */
.product-detail-header-actions .wishlist-toggle {
  position: static;
  width: 36px;
  height: 36px;
  color: var(--text-primary);
  filter: none;
}

/* Специфичность правила выше .wishlist-toggle--active — без этого override
   активное (красное) сердце на деталке перекрывалось бы обычным цветом. */
.product-detail-header-actions .wishlist-toggle--active {
  color: #e0245e;
}

.product-card-preview {
  cursor: pointer;
  display: flex;
  flex-direction: column;
  flex: 1;
  -webkit-tap-highlight-color: transparent;
}

.product-card-preview:active { opacity: 0.75; }

.product-img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--surface2);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-hint);
  font-size: 32px;
}

.product-info {
  padding: var(--sp-2) var(--sp-3) var(--sp-3);
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  flex: 1;
}

.product-name {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--text-primary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product-price {
  font-size: 15px;
  font-weight: 700;
  color: var(--accent);
}

.product-card-action {
  padding: 0 var(--sp-3) var(--sp-3);
}

/* ── Add button ──────────────────────────────────────────────────────────── */
.add-btn {
  width: 100%;
  height: var(--touch);
  border: none;
  border-radius: var(--r-sm);
  background: var(--accent);
  color: var(--accent-text);
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  transition: opacity 0.15s ease;
}

.add-btn:active:not([disabled]) { opacity: 0.8; }

.add-btn[disabled] {
  background: color-mix(in srgb, var(--accent) 15%, var(--surface));
  color: var(--accent);
  cursor: default;
  opacity: 1;
}

/* Нет в наличии: карточка приглушена, кнопка недоступна. */
/* Товар «немає в наявності»: приглушаем всю верхнюю часть карточки, не
   только фото — без фото (плейсхолдер) карточка иначе неотличима от
   доступной, пока не прочитаешь текст кнопки. */
.product-card--oos .product-img { opacity: 0.5; }
.product-card--oos .product-info { opacity: 0.55; }

.add-btn--oos,
.add-btn--oos[disabled] {
  background: var(--surface2);
  color: var(--text-hint);
  cursor: default;
}

/* Поиск по чипам внутри фильтр-шита. */
.filter-search {
  -webkit-appearance: none;
  appearance: none;
  margin: 0 var(--sp-4) var(--sp-2);
  padding: 8px 12px;
  border: 1px solid var(--divider);
  border-radius: 10px;
  /* iOS Safari auto-zooms on focus for inputs under 16px; override --text-sm to prevent it. */
  font-size: 16px;
  background: var(--surface);
  color: var(--text-primary);
  font-family: inherit;
}

/* Шапка «Назад» на деталке товара — без заголовка, только кнопка. */
.product-detail-back { padding-bottom: 0; }

.add-btn--in-cart {
  background: transparent;
  color: var(--accent);
  border: 2px solid var(--accent);
}

.add-btn-badge {
  background: var(--accent);
  color: var(--accent-text);
  font-size: 11px;
  font-weight: 700;
  min-width: 20px;
  height: 20px;
  border-radius: 10px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
  line-height: 1;
}

/* Намекает, что тап по кнопке «в кошику» добавляет ещё одну единицу,
   а не просто показывает статус. */
.add-btn-badge-plus {
  opacity: 0.7;
  font-weight: 500;
}

/* Тот же намёк на кнопке «до кошика»: плюсик рядом с текстом,
   чтобы поведение читалось одинаково до и после добавления товара. */
.add-btn-plus {
  opacity: 0.7;
  font-weight: 500;
}

/* ── Infinite scroll ─────────────────────────────────────────────────────── */
/* Сентинел подгрузки следующей страницы: hx-trigger="revealed" стреляет,
   когда элемент доскроллен до видимости; ответ заменяет его карточками
   и новым сентинелом. */
.load-sentinel {
  grid-column: 1 / -1;
  display: flex;
  justify-content: center;
  padding: var(--sp-4) 0;
}

.load-spinner {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2.5px solid var(--divider);
  border-top-color: var(--accent);
  animation: spinAnim 0.8s linear infinite;
}

@keyframes spinAnim {
  to { transform: rotate(360deg); }
}

/* ── Cart ────────────────────────────────────────────────────────────────── */
.cart-page { padding-bottom: var(--sp-4); }

.cart-page-header {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  position: sticky;
  top: 0;
  background: var(--bg);
  z-index: 10;
  border-bottom: 1px solid var(--divider);
}

.cart-back-btn {
  border: none;
  background: none;
  color: var(--link);
  font-size: var(--text-md);
  font-weight: var(--fw-normal);
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: var(--touch);
  padding: 0;
}

.cart-back-btn:active { opacity: 0.6; }

/* На ios/android Telegram уже рисует нативную BackButton в своей шапке —
   свои back-контролы там лишние (см. app.js: init()). */
body.tg-native-back .cart-back-btn { display: none; }
body.tg-native-back .product-detail-back { display: none; }

.cart-page-header h2 {
  font-size: var(--text-lg);
  font-weight: var(--fw-semi);
  flex: 1;
}

.cart-items {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--divider);
  margin: var(--sp-2) var(--sp-4) 0;
  border-radius: var(--r-lg);
  overflow: hidden;
}

.cart-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  background: var(--surface);
  padding: var(--sp-3) var(--sp-4);
  min-height: 72px;
}

.cart-item-img {
  width: 52px;
  height: 52px;
  border-radius: var(--r-sm);
  object-fit: cover;
  background: var(--surface2);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-hint);
  font-size: 22px;
  flex-shrink: 0;
}

.cart-item-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.cart-item-name {
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cart-item-price {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.cart-item-qty {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-shrink: 0;
}

.qty-btn {
  width: var(--touch);
  height: var(--touch);
  border-radius: var(--r-sm);
  border: none;
  background: var(--surface2);
  color: var(--accent);
  font-size: 20px;
  font-weight: var(--fw-semi);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.15s ease;
}

.qty-btn:active { opacity: 0.6; }

.qty-value {
  font-size: var(--text-md);
  font-weight: var(--fw-semi);
  min-width: 20px;
  text-align: center;
  color: var(--text-primary);
}

.cart-item-subtotal {
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
  flex-shrink: 0;
  min-width: 56px;
  text-align: right;
}

/* ── Cart summary ────────────────────────────────────────────────────────── */
.cart-summary {
  padding: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.cart-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: var(--text-lg);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
}

/* Промокод в корзине */
.cart-promo-form {
  display: flex;
  gap: var(--sp-2);
}

.cart-promo-input {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--divider);
  border-radius: 10px;
  /* iOS Safari auto-zooms on focus for inputs under 16px; override --text-md to prevent it. */
  font-size: 16px;
  background: var(--surface);
  color: var(--text-primary);
  /* Введённый код показываем капсом (промокоды канонично uppercase),
     но плейсхолдер «Промокод» — обычная строка, капс на нём кричит. */
  text-transform: uppercase;
}

.cart-promo-input::placeholder { text-transform: none; }

.cart-promo-apply,
.cart-promo-remove {
  -webkit-appearance: none;
  appearance: none;
  border: 1px solid var(--divider);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
}

.cart-promo-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: var(--text-md);
  color: var(--text-primary);
}

.cart-subtotal,
.cart-discount {
  font-size: var(--text-md);
  font-weight: var(--fw-regular, 400);
  color: var(--text-hint);
}

.cart-discount span:last-child {
  color: var(--accent, #16a34a);
}

.cart-empty {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  align-items: center;
  text-align: center;
  padding: 64px var(--sp-4);
  color: var(--text-hint);
  font-size: var(--text-md);
}

/* ── Checkout button ─────────────────────────────────────────────────────── */
.checkout-btn {
  width: 100%;
  height: 52px;
  border: none;
  border-radius: var(--r-md);
  background: var(--accent);
  color: var(--accent-text);
  font-size: var(--text-md);
  font-weight: var(--fw-semi);
  font-family: inherit;
  cursor: pointer;
  transition: opacity 0.15s ease;
}

.checkout-btn:active { opacity: 0.8; }
.checkout-btn[disabled] { opacity: 0.5; cursor: default; }

/* ── Delivery form ────────────────────────────────────────────────────────── */
/* Форма — картка (.surface) з інсетом sp-4, щоб поля збігались із «До сплати»
   і не липли до країв (раніше форму винесли з .cart-summary і вона втратила
   паддінг). Поля всередині — на --bg: гарантований контраст із карткою в обох
   темах, вигляд «утоплених» інпутів. */
.delivery-form {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  margin: 0 var(--sp-4);
  padding: var(--sp-4);
  background: var(--surface);
  border-radius: var(--r-lg);
}

/* Перевізник — вертикальні пілюлі, що виділяються при виборі (:has(:checked)),
   замість дрібних нативних радіо. Радіо лишається як індикатор ліворуч. */
.delivery-carrier-group {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.delivery-carrier-option {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--touch);
  padding: 0 var(--sp-3);
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  background: var(--bg);
  font-size: var(--text-md);
  color: var(--text-primary);
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.delivery-carrier-option:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.delivery-input {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  min-height: var(--touch);
  padding: 0 var(--sp-3);
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  /* iOS Safari auto-zooms on focus for inputs under 16px; override --text-md to prevent it. */
  font-size: 16px;
  background: var(--bg);
  color: var(--text-primary);
  font-family: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.delivery-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);
}

.delivery-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.delivery-field.hidden {
  display: none;
}

.delivery-label {
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  color: var(--text-secondary);
  padding-left: 2px;
}

.delivery-input--invalid {
  border-color: var(--destructive);
}

.delivery-input--invalid:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--destructive) 20%, transparent);
}

/* ── Product detail ──────────────────────────────────────────────────────── */
.product-detail {
  background: var(--surface);
  margin: var(--sp-4);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.product-detail .product-img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.product-carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}

.product-carousel .product-img {
  flex: 0 0 100%;
  scroll-snap-align: start;
}

.product-carousel-dots {
  display: flex;
  justify-content: center;
  gap: 6px;
  padding: var(--sp-2, 8px) 0;
}

.product-carousel-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border, #ccc);
}

.product-carousel-dot--active {
  background: var(--accent, #333);
}

.product-detail-info {
  padding: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.product-detail-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--sp-3);
}

.product-detail-header-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-shrink: 0;
}

.product-share-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
}

.product-detail-name {
  flex: 1;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--text-primary);
}

.product-detail-price {
  font-size: 20px;
  font-weight: 700;
  color: var(--accent);
  flex-shrink: 0;
}

.product-detail-desc {
  font-size: var(--text-md);
  color: var(--text-secondary);
  line-height: 1.5;
}

.product-detail-specs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--divider);
}

.product-detail-spec {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  background: var(--surface2);
}

.product-detail-spec svg {
  color: var(--accent);
  flex-shrink: 0;
}

.product-detail-spec-value {
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
  display: block;
}

.product-detail-spec-label {
  font-size: 11px;
  color: var(--text-hint);
  display: block;
}

.related-products {
  padding-top: var(--sp-2);
  border-top: 1px solid var(--divider);
}

.related-products-title {
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  color: var(--text-secondary);
  margin-bottom: var(--sp-2);
}

.related-products-strip {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.related-products-strip::-webkit-scrollbar { display: none; }

.related-product-card {
  flex: 0 0 108px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.related-product-card:active { opacity: 0.75; }

.related-product-card .product-img {
  border-radius: var(--r-md);
}

.related-product-name {
  font-size: 11px;
  line-height: 1.25;
  margin-top: var(--sp-1);
  color: var(--text-primary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.related-product-price {
  font-weight: 700;
  font-size: 12px;
  color: var(--accent);
  margin-top: 2px;
}

/* ── Product photo zoom ──────────────────────────────────────────────────── */
.product-media-zoomable {
  position: relative;
}

.zoom-hint {
  position: absolute;
  right: var(--sp-3);
  bottom: var(--sp-3);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 20px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 11px;
  pointer-events: none;
}

/* z-index 400: above .cart-bar/.cart-fab (200) and .view-overlay (150) that
   the zoom overlay must cover regardless of which screen it was opened
   from, below .toast (999). */
.zoom-overlay {
  position: fixed;
  inset: 0;
  z-index: 400;
  background: rgba(0, 0, 0, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
}

.zoom-close {
  position: absolute;
  /* z-index: 1 — .zoom-image gets its own stacking context from `transform`
     when zoomed (2x scale can visually cover this corner); without an
     explicit z-index here the two would stack by DOM order (image last =
     on top), making the button unreachable while zoomed. */
  z-index: 1;
  top: calc(var(--sp-4) + env(safe-area-inset-top));
  right: var(--sp-4);
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.zoom-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  transition: transform 0.2s ease;
  touch-action: none;
}

/* Липкий CTA поверх overlay-екрана (детальна, крок 1 кошика). sticky, а не
   fixed: .view-overlay має transform, тож fixed-нащадок рахується від оверлея
   й скролиться з контентом. Свій safe-area паддінг знизу (padding-bottom
   оверлея на такому екрані обнулено — див. нижче). Має бути прямим нащадком
   .view-overlay. */
.overlay-cta {
  position: sticky;
  bottom: 0;
  padding: var(--sp-2) var(--sp-4) calc(var(--sp-2) + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--divider);
  z-index: 160;
}

/* Пока фокус в поле оверлея (открыта клавиатура), липкий CTA скрыт: на
   ужатом экране он съедает ~65px и накрывает нижние поля формы. Класс
   ставит/снимает setupOverlayKeyboard (app.js). */
.view-overlay--kb .overlay-cta {
  display: none;
}

/* Overlay з липким CTA стає flex-колонкою, .overlay-body тягнеться (flex:1),
   щоб футер сідав на низ навіть коли контенту менше за екран (без прокрутки
   sticky інакше зависає посередині). padding-bottom оверлея обнуляється —
   відступ від home-indicator дає власний safe-area футера. :has не тримає
   старий WebView (як і решта :has-правил у файлі) — там футер лишається
   sticky без розтягування, деградація допустима. */
.view-overlay:has(> .overlay-cta) {
  display: flex;
  flex-direction: column;
  padding-bottom: 0;
}

.view-overlay:has(> .overlay-cta) > .overlay-body {
  flex: 1 0 auto;
}

/* Ховаємо x-show-елементи до ініціалізації Alpine, щоб обидва кроки кошика не
   блимнули разом при вставці фрагмента. */
[x-cloak] { display: none !important; }

/* Сума «До сплати» над формою доставки: окремий summary-рядок з роздільником,
   сума акцентно-крупна, підпис приглушений. */
.cart-step2-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: var(--sp-3) var(--sp-4) var(--sp-4);
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--divider);
  font-size: var(--text-md);
  color: var(--text-secondary);
}

.cart-step2-total > span:last-child {
  font-size: var(--text-lg);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
}

/* OOB-таргет счётчика корзины — всегда скрыт, виден только через Alpine */
#cart-count { display: none; }

/* ── Cart bar ────────────────────────────────────────────────────────────── */
.cart-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: calc(56px + env(safe-area-inset-bottom));
  padding: 0 var(--sp-4) env(safe-area-inset-bottom);
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-family: inherit;
  font-size: var(--text-md);
  font-weight: var(--fw-semi);
  cursor: pointer;
  z-index: 200;
  -webkit-tap-highlight-color: transparent;
  appearance: none;
  -webkit-appearance: none;
}

.cart-bar:active { opacity: 0.85; }

/* Пока фокус в любом текстовом поле (открыта клавиатура), бар корзины
   скрыт — иначе он всплывает над клавиатурой и накрывает результаты
   каталога при поиске. body.kb-focus ставит setupOverlayKeyboard (app.js);
   x-show Alpine при скрытии пишет inline display:none — правила не
   конфликтуют, оба прячут. */
body.kb-focus .cart-bar { display: none; }

.cart-bar-icon { flex-shrink: 0; }
.cart-bar-label { flex: 1; text-align: left; }

.cart-bar-count {
  color: color-mix(in srgb, var(--accent-text) 70%, transparent);
  font-size: var(--text-sm);
}

.cart-bar-arrow { font-size: var(--text-lg); }

.cart-bar.bump { animation: bumpAnim 0.3s ease; }

/* ── Cart FAB (detail view) ─────────────────────────────────────────────── */
.cart-fab {
  position: fixed;
  bottom: calc(72px + env(safe-area-inset-bottom));
  right: var(--sp-4);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  appearance: none;
  -webkit-appearance: none;
}

.cart-fab:active { opacity: 0.85; }
.cart-fab.bump { animation: bumpAnim 0.3s ease; }

.cart-fab-count {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 20px;
  height: 20px;
  border-radius: 10px;
  background: var(--surface);
  color: var(--accent);
  border: 2px solid var(--accent);
  font-size: 11px;
  font-weight: 700;
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.product-card--bump { animation: bumpAnim 0.3s ease; }

/* ── Order confirmation ──────────────────────────────────────────────────── */
.order-confirmation-icon {
  display: flex;
  justify-content: center;
  padding: var(--sp-6) 0 var(--sp-2);
  color: var(--accent);
}

.order-confirmation-title {
  text-align: center;
  font-size: var(--text-lg);
  font-weight: var(--fw-semi);
  padding: 0 var(--sp-4) var(--sp-2);
}

/* Строка статуса под заголовком при просмотре заказа из истории. */
.order-status-line {
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  padding: 0 var(--sp-4) var(--sp-2);
}

.order-status-line--cancelled { color: var(--destructive); }

/* ── Экран ожидания онлайн-оплаты ────────────────────────────────────────── */
/* Наследует .cart-page: те же отступы и фон, что у корзины и чека. */
.order-payment-total,
.order-payment-timer {
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  padding: 0 var(--sp-4) var(--sp-2);
}

/* Моноширинный, чтобы цифры не прыгали по ширине на каждой секунде. */
.order-payment-timer-value {
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-semi);
  color: var(--text-primary);
}

.order-payment-actions {
  padding: var(--sp-2) var(--sp-4);
}

.order-payment-hint {
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  padding: var(--sp-2) var(--sp-6) var(--sp-4);
  line-height: 1.45;
}

/* CTA в пустой корзине — под текстом, а не во всю ширину экрана. */
.cart-empty .cart-empty-cta { width: auto; padding-left: var(--sp-6); padding-right: var(--sp-6); }

/* ── Toast ───────────────────────────────────────────────────────────────── */
.toast {
  position: fixed;
  bottom: calc(72px + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  background: color-mix(in srgb, var(--text-primary) 88%, transparent);
  color: var(--surface);
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-md);
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  z-index: 999;
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
  white-space: nowrap;
  max-width: calc(100vw - 48px);
  text-align: center;
}

.toast.visible { opacity: 1; }

/* ── View overlay (cart/product-detail push navigation) ─────────────────── */
/* Catalog stays live underneath in #catalog-container; cart/detail render
   into one of these instead of replacing it. z-index 150 sits above
   .filter-bar (100) but BELOW .cart-bar (200): видимостью карт-бара
   управляет x-show (view !== 'cart'), а не стекинг — на экранах detail и
   истории заказов бар должен оставаться видимым и кликабельным поверх
   оверлея (вложенный кейс detail → cart). .sheet-overlay/.filter-sheet
   (300/301) и .toast (999) остаются поверх любого экрана. */
.view-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* height (не inset: 0 снизу) — на iOS Safari/WebView fixed+inset:0
     считает высоту от "большого" viewport (когда адресная строка
     скрыта), из-за чего контент внизу (checkout-btn) уезжает за
     пределы реально видимой области, а если контента внутри не
     хватает, чтобы переполнить этот раздутый бокс, скроллить нечего.
     --tg-vh (app.js: updateTgViewportHeight, из tg.viewportStableHeight)
     точнее внутри Telegram WebView; 100dvh — фолбэк вне Telegram. */
  height: var(--tg-vh, 100dvh);
  z-index: 150;
  overflow-y: auto;
  /* Без -webkit-overflow-scrolling на WKWebView (Telegram iOS) тач-свайп
     внутри overflow:auto, вложенного в position:fixed, иногда не
     заводит нативный скролл вовсе — при этом programmatic scrollTop
     работает, так что баг не проявляется в Playwright/devtools. */
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  /* Тот же нижний отступ, что и у body: контент оверлея (кнопки внизу
     detail/чека) не должен прятаться под фиксированным cart-bar. */
  padding-bottom: calc(80px + env(safe-area-inset-bottom));
  /* Основная защита от iOS rubber-band, задирающего каталог под оверлеем:
     на iOS WebKit надёжен именно overscroll-behavior, а не overflow на body. */
  overscroll-behavior: contain;
  background: var(--bg);
  transform: translateX(100%);
  transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1);
}

.view-overlay--visible { transform: translateX(0); }

/* Вторая линия защиты от скролла базы под оверлеем. :has() требует
   Chrome 105+ / iOS 15.4+ — на более старых WebView правило молча
   не применится, деградация приемлемая. */
body:has(.view-overlay) { overflow: hidden; }

/* ── States ──────────────────────────────────────────────────────────────── */
.loading {
  text-align: center;
  padding: 64px var(--sp-4);
  color: var(--text-hint);
  font-size: var(--text-md);
}

/* Пустое состояние каталога (ничего не найдено по фильтрам). */
.catalog-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  padding: 64px var(--sp-4);
  color: var(--text-hint);
  font-size: var(--text-md);
  text-align: center;
}

.catalog-empty-icon { opacity: 0.5; }

.catalog-maintenance-icon { opacity: 0.6; }

.catalog-maintenance-heading {
  font-size: var(--text-lg);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
}

.maintenance-nozzle {
  animation: maintenance-nozzle-move 2.4s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}
@keyframes maintenance-nozzle-move {
  0%   { transform: translate(-5px, -4px); }
  25%  { transform: translate(5px, -4px); }
  50%  { transform: translate(5px, 4px); }
  75%  { transform: translate(-5px, 4px); }
  100% { transform: translate(-5px, -4px); }
}

.maintenance-bars { animation: maintenance-bars-blink 1.8s ease-in-out infinite; }
@keyframes maintenance-bars-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}

.maintenance-zzz { animation: maintenance-zzz-float 2s ease-in-out infinite; }
@keyframes maintenance-zzz-float {
  0%, 100% { transform: translateY(0); opacity: 0.4; }
  50%      { transform: translateY(-4px); opacity: 0.9; }
}

@media (prefers-reduced-motion: reduce) {
  .maintenance-nozzle, .maintenance-bars, .maintenance-zzz { animation: none; }
}

.error-box {
  text-align: center;
  padding: 48px var(--sp-4);
  color: var(--destructive);
  font-size: var(--text-md);
}

/* ── Фасетные фильтры каталога ──────────────────────────────────────────── */
/* Sticky-бар над каталогом: кнопка шита + горизонтальная лента активных тегов.
   Живёт в layout, HTMX его не трогает — остаётся на месте при скролле и
   подменах контента. */
.filter-bar {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  background: var(--bg);
  border-bottom: 1px solid var(--divider);
}

.filter-bar--elevated {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* Верхняя строка: кнопка фильтров слева, кластер иконок/локали справа
   (margin-left: auto на .filter-bar-icons — работает и когда фильтров нет,
   т.е. .filter-toggle не отрендерен вовсе). Лента активных тегов — отдельной
   строкой ниже, чтобы не толкать иконки при нескольких выбранных тегах. */
.filter-bar-top {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.filter-bar-icons {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
}

.filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 36px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text-primary);
  font-size: var(--text-md);
  font-weight: var(--fw-semi);
  font-family: inherit;
  cursor: pointer;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
}

/* Кнопка «Мои заказы» — открывает историю заказов оверлеем (pushView). */
.history-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
}

.refresh-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
}

.search-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
}

/* Строка поиска — видимость через класс .open (Alpine :class), без x-show:
   input.focus() сразу после снятия display:none не поднимает клавиатуру в
   Telegram WebView на iOS (фокус формально ставится — видна рамка — но
   клавиатура не появляется). Держим элемент в layout всегда и анимируем
   max-height/opacity, как .filter-sheet. */
.search-row {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  transition: max-height 0.2s ease, opacity 0.2s ease, margin-top 0.2s ease;
}

.search-row.open {
  max-height: 60px;
  opacity: 1;
  margin-top: var(--sp-2);
  pointer-events: auto;
}

.search-input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--divider);
  border-radius: 10px;
  /* iOS Safari auto-zooms on focus for inputs under 16px; override --text-md to prevent it. */
  font-size: 16px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text-primary);
  outline: none;
}

.search-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
}

/* Лента активных фильтров: отдельная строка под .filter-bar-top, скроллится
   горизонтально, скроллбар скрыт. min-width:0 нужен, чтобы flex-column
   родитель не растягивал ленту по контенту вместо ширины экрана. */
.active-chips {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  min-width: 0;
}

.active-chips::-webkit-scrollbar { display: none; }

.active-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: 32px;
  padding: var(--sp-1) var(--sp-3);
  border: none;
  border-radius: 16px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  appearance: none;
  -webkit-appearance: none;
}

.active-chip:active { opacity: 0.8; }

.active-chip-x {
  font-size: var(--text-md);
  line-height: 1;
  opacity: 0.7;
}

.filter-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
}

/* Переключатель языка витрины: отделён от кластера search/history/refresh
   заметным отступом — margin-left: auto здесь бесполезен (родитель
   .filter-bar-icons сжимается по контенту, свободного места распределять
   нечего), поэтому разделение задаётся явным отступом, а не флекс-трюком. */
.locale-switcher {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  margin-left: var(--sp-3);
  flex-shrink: 0;
  border: 1px solid var(--divider);
  border-radius: var(--r-md);
  background: var(--surface);
}

.locale-btn {
  min-height: 30px;
  padding: 0 var(--sp-2);
  border: none;
  border-radius: calc(var(--r-md) - 2px);
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  font-family: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none; /* iOS: иначе стиль кнопки перекрывает background */
}

.locale-btn--active {
  background: var(--accent);
  color: var(--accent-text);
}

.filter-caret {
  color: var(--text-hint);
  font-size: var(--text-sm);
}

/* ── Bottom sheet фильтров ──────────────────────────────────────────────── */
/* Видимость — чисто CSS через класс .open (Alpine :class), без x-show:
   шит выезжает снизу transform-переходом, оверлей растворяется opacity. */
.sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(0, 0, 0, 0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

.sheet-overlay.open {
  opacity: 1;
  pointer-events: auto;
}

.filter-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 301;
  display: flex;
  flex-direction: column;
  max-height: 70vh;
  background: var(--surface);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  transform: translateY(100%);
  transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1);
  padding-bottom: env(safe-area-inset-bottom);
}

.filter-sheet.open { transform: translateY(0); }

.filter-sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-4) var(--sp-4) var(--sp-2);
  flex-shrink: 0;
}

.filter-sheet-header h3 {
  font-size: var(--text-lg);
  font-weight: var(--fw-semi);
}

.sheet-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 16px;
  background: var(--surface2);
  color: var(--text-hint);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.sheet-close:active { opacity: 0.6; }

.filter-sheet-body {
  overflow-y: auto;
  padding: var(--sp-2) var(--sp-4);
}

.filter-sheet-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--divider);
  flex-shrink: 0;
}

.filter-group {
  border: 0;
  margin: 0 0 var(--sp-3);
  padding: 0;
}

.filter-legend {
  padding: 0 0 var(--sp-2);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
}

.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--divider);
  border-radius: 17px;
  background: var(--surface2);
  color: var(--text-primary);
  font-size: var(--text-sm);
  cursor: pointer;
  user-select: none;
}

/* Скрываем нативный чекбокс — состояние выражаем стилем самого чипа. */
.filter-chip input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.filter-chip:has(input:checked) {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}

.filter-reset,
.filter-apply {
  min-height: 44px;
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-md);
  font-size: var(--text-md);
  font-weight: var(--fw-semi);
  font-family: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.filter-reset {
  border: 1px solid var(--divider);
  background: var(--surface);
  color: var(--text-primary);
}

.filter-apply {
  border: 0;
  background: var(--accent);
  color: var(--accent-text);
}

/* ── Широкие вьюпорты ────────────────────────────────────────────────────── */
/* Telegram открывает Mini App в окне телефонной ширины даже на десктопе и
   iPad, так что этот блок виден в основном в браузерном dev-режиме (и в
   потенциальном fullscreen-режиме, если он появится). Лейаут остаётся
   мобильным одноколоночным — контент просто капается по ширине и центрируется.
   Про полноценный multi-column см.
   docs/superpowers/specs/2026-07-16-wide-viewport-notes.md. */
@media (min-width: 600px) {
  #catalog-container {
    max-width: 520px;
    margin-inline: auto;
  }

  /* Капаем сам .view-overlay, а не его детей: .view-overlay:has(> .overlay-cta)
     делает оверлей flex-колонкой, и max-width+margin:auto на детях схлопывал бы
     их до ширины контента (margin:auto по cross-оси flex — так футер/деталка и
     «сжимались» на широком экране). Слайд translateX работает в пределах
     520px-бокса. Фикс-полосы капаются через left/right, без transform:
     translateX(-50%) конфликтовал бы с bump-анимацией карт-бара. */
  .view-overlay,
  .cart-bar,
  .filter-sheet {
    left: max(0px, calc(50% - 260px));
    right: max(0px, calc(50% - 260px));
  }

  .cart-fab {
    right: max(var(--sp-4), calc(50% - 260px + var(--sp-4)));
  }

  /* Сам бар остаётся во всю ширину (sticky-фон и border-bottom), а контент
     выравнивается по колонке каталога. */
  .filter-bar {
    padding-inline: max(var(--sp-4), calc(50% - 260px + var(--sp-4)));
  }
}

/* ── Order history ───────────────────────────────────────────────────────── */
.order-history-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--divider);
  margin: var(--sp-2) var(--sp-4) 0;
  border-radius: var(--r-lg);
  overflow: hidden;
}

.order-history-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  background: var(--surface);
  border: none;
  padding: var(--sp-3) var(--sp-4);
  min-height: 56px;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}

.order-history-row:active { opacity: 0.7; }

.order-history-row-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.order-history-row-id {
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
}

.order-history-row-date {
  font-size: var(--text-sm);
  color: var(--text-hint);
}

/* Статус — цветная пилюля: pending нейтрально-янтарный, confirmed акцентный,
   shipped зелёный, cancelled destructive. Иконка внутри тинтуется currentColor.
   Неизвестный статус падает на нейтральный дефолт. */
.order-history-row-status {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  flex-shrink: 0;
  padding: 3px var(--sp-2);
  border-radius: 20px;
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  background: color-mix(in srgb, var(--text-primary) 8%, transparent);
  color: var(--text-secondary);
}

/* awaiting_payment — единственный статус, требующий действия покупателя,
   поэтому оранжевый, а не жёлтый «в обработке»: пара повторяет
   .adm-status-badge--awaiting_payment в админке. */
.order-status--awaiting_payment {
  background: color-mix(in srgb, #f97316 16%, transparent);
  color: #f97316;
}

.order-status--pending {
  background: color-mix(in srgb, #e6a23c 16%, transparent);
  color: #e6a23c;
}

.order-status--confirmed {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent);
}

.order-status--shipped {
  background: color-mix(in srgb, #22c55e 18%, transparent);
  color: #22c55e;
}

.order-status--cancelled {
  background: color-mix(in srgb, var(--destructive) 16%, transparent);
  color: var(--destructive);
}

.order-history-row-total {
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  color: var(--text-primary);
  flex-shrink: 0;
  min-width: 56px;
  text-align: right;
}

/* ── Preorder («під замовлення») ─────────────────────────────────────────── */

.preorder-badge {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: var(--sp-1);
  padding: 3px var(--sp-2);
  border-radius: 20px;
  font-size: var(--text-sm);
  font-weight: var(--fw-semi);
  line-height: 1.3;
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  color: var(--accent);
  /* Не nowrap: order_confirmation.templ рендерит этот класс с текстом
     ("N шт. під замовлення") — в узкой колонке .cart-item-info длинный
     текст иначе не сужается вместе с колонкой, а вылезает вправо поверх
     соседей; max-width ограничивает бейдж шириной родителя, чтобы было
     куда переноситься. */
  max-width: 100%;
}

.preorder-badge svg {
  flex-shrink: 0;
}

/* Вариант только с иконкой (cart.templ) — расшифровка вынесена в общую
   .preorder-note под списком вместо повторения текста в каждой строке. */
.preorder-badge--icon-only {
  padding: 3px;
  border-radius: 50%;
}

.preorder-note,
.order-cancelled-note {
	margin: var(--sp-2) var(--sp-4) 4px;
	font-size: 12px;
	line-height: 1.4;
	color: var(--tg-theme-hint-color, #8e8e93);
}

/* .preorder-note маркирована той же иконкой (@iconClock), что и бейдж в
   строке корзины — визуальная связка "эта иконка = вот что она значит"
   без наведения (тач-интерфейс, hover недоступен). */
.preorder-note {
  display: flex;
  align-items: flex-start;
  gap: 4px;
}

.preorder-note-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--accent);
  margin-top: 1px;
}

.order-delivery-info {
  margin: var(--sp-3) var(--sp-4) 0;
  padding: var(--sp-3);
  border-radius: var(--r-md);
  background: var(--surface-secondary, var(--surface));
  font-size: var(--text-sm);
  color: var(--text-primary);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.order-delivery-comment {
  color: var(--text-hint);
}

/* ── Reduced motion ──────────────────────────────────────────────────────── */
/* Universal override, not per-keyframe rules — collapses every animation/
   transition in this stylesheet (present and future) to near-instant. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
