:root {
  --bg: #faf8f6;
  --card-bg: #ffffff;
  --ink: #333333;
  --ink-muted: #8a8783;
  --ink-faint: #bcb8b3;
  --accent: #fe7701;
  --accent-ink: #ffffff;
  --badge-bg: #fff1e2;
  --badge-ink: #b45a02;
  --badge-bg-off: #eeecea;
  --badge-ink-off: #8a8783;
  --ok: #1fa564;
  --ok-bg: #e7f8ee;
  --line: #eeecea;
  --warn-bg: #fff3e0;
  --warn-ink: #8a5a10;
  --error-bg: #fdeceb;
  --error-ink: #b3271e;
  --dark: #333333;
  --dark-ink: #ffffff;
  --dark-muted: rgba(255, 255, 255, 0.5);
  --dark-pill-bg: rgba(255, 255, 255, 0.13);
  --radius-card: 18px;
  --radius-pill: 999px;
  --shadow: 0 1px 2px rgba(20, 20, 25, 0.04);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.4 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, sans-serif;
  padding-bottom: 84px; /* clears the fixed bottom nav */
}

a { color: inherit; text-decoration: none; }

/* ---- Top bar ---- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--dark);
  padding: 18px 16px 16px;
  border-radius: 0 0 20px 20px;
}
.topbar .brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.brand .logo {
  display: flex;
  align-items: center;
  gap: 8px;
}
.brand .logo img,
.brand .logo svg { height: 26px; width: auto; display: block; }
.brand h1 {
  font-size: 20px;
  margin: 0;
  color: var(--dark-ink);
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.back-link {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
  margin-right: 12px;
}
.back-link svg {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--dark-ink);
}
.wordmark {
  flex: none;
  color: var(--accent);
  font-weight: 800;
  font-size: 21px;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.brand-home-link {
  display: inline-flex;
  align-items: center;
  border-radius: 6px;
  text-decoration: none;
}
.brand-home-link:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 3px;
}

/* ---- Client row (name + logout) ---- */
.client-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12.5px;
  color: var(--dark-muted);
}
.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--dark-muted);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* ---- Banner ---- */
.home-banner {
  display: block;
  width: calc(100% - 32px);
  height: auto;
  margin: 16px 16px 4px;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}

/* ---- Category cards (right side: count + chevron) ---- */
.cat-right {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
}
.count-pill {
  min-width: 28px;
  text-align: center;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--badge-bg);
  color: var(--badge-ink);
  font-size: 13px;
  font-weight: 700;
}
.chevron { width: 18px; height: 18px; color: var(--ink-faint); }

/* ---- Callouts ---- */
.callout {
  margin: 0 16px 12px;
  padding: 12px 14px;
  border-radius: 14px;
  font-size: 13.5px;
}
.callout.warn { background: var(--warn-bg); color: var(--warn-ink); }
.callout.error { background: var(--error-bg); color: var(--error-ink); }

/* ---- Product list ---- */
.list { padding: 4px 16px 16px; display: flex; flex-direction: column; gap: 10px; }

.card {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  padding: 12px;
  box-shadow: var(--shadow);
}

/* Product cards wrap their thumb+body in this link so the row opens the
   product page, while the price/add-to-cart column stays outside it —
   a <button>/<form> can't legally nest inside an <a>. */
.card-link {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.thumb {
  position: relative;
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 13px;
  background-color: var(--badge-bg);
  background-size: cover;
  background-position: center;
  color: var(--badge-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.02em;
}

/* ---- Акції/Новинки: badges shown on a product thumb ---- */
.product-badges {
  position: absolute;
  top: -4px;
  right: -4px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}
.product-badge {
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  font-size: 9px;
  font-weight: 700;
  line-height: 1.6;
  white-space: nowrap;
}
.product-badge-sale { background: var(--error-ink); color: #fff; }
.product-badge-new { background: var(--accent); color: var(--accent-ink); }

/* ---- Акції та новинки: home-page promo carousel ---- */
.promo-carousel { margin-top: 6px; }
.promo-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 16px 16px 7px;
}
.promo-header h2 { margin: 0; font-size: 14px; line-height: 1.3; font-weight: 700; }
/* Always visible -- the JS already fades/disables an arrow that has
   nothing left to scroll to, so this alone reflects real overflow
   rather than a window-width guess (see .promo-card below for why). */
.promo-arrows { display: flex; gap: 8px; }
.promo-arrow {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: var(--badge-bg);
  color: var(--badge-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.promo-arrow:disabled { opacity: 0.35; cursor: default; }

.promo-track {
  display: flex;
  gap: 12px;
  padding: 4px 16px 6px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  cursor: grab;
}
.promo-track::-webkit-scrollbar { display: none; }
.promo-track.dragging { cursor: grabbing; scroll-snap-type: none; scroll-behavior: auto; }
@media (prefers-reduced-motion: reduce) {
  .promo-track { scroll-behavior: auto; }
}

/* Body itself is capped at max-width:480px past 560px viewport (see
   "Wider screens: keep it phone-shaped, don't stretch" below) -- this
   app never actually gets wider than that container, on any screen. A
   width keyed to window min-width breakpoints was therefore keying off
   a number the container never reflects: past 1024px viewport width
   the card was still sized against the same ~480px box, just against a
   smaller percentage of it, so cards shrank as the window widened
   instead of the layout just staying constant. One width, sized for
   two full cards (plus a peeking third) within that ~480px container
   on every screen. */
.promo-card {
  position: relative;
  flex: 0 0 auto;
  width: 44%;
  display: flex;
  flex-direction: column;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  padding: 10px;
  scroll-snap-align: start;
}

.promo-card-link { display: flex; flex-direction: column; gap: 8px; color: inherit; text-decoration: none; }
.promo-thumb {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 13px;
  background: var(--badge-bg);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.promo-img { width: 100%; height: 100%; object-fit: cover; }
.promo-thumb .thumb-leaf { width: 46%; height: auto; opacity: 0.55; }
.promo-name {
  font-weight: 600;
  font-size: 13.5px;
  line-height: 1.3;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.promo-footer {
  margin-top: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.promo-price { display: flex; flex-direction: column; }
.promo-card .fav-form { top: 8px; left: 8px; }

.promo-dots { display: flex; justify-content: center; gap: 6px; margin-top: 6px; }
.promo-dot {
  width: 6px;
  height: 6px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: var(--badge-bg-off);
}
.promo-dot.active { width: 16px; background: var(--accent); }
.thumb-leaf { width: 46%; height: auto; opacity: 0.55; }
.thumb[style*="background-image"] .thumb-leaf,
.thumb.has-image .thumb-leaf { display: none; }

.card-body { flex: 1; min-width: 0; }
.card-name {
  font-weight: 600;
  font-size: 14.5px;
  line-height: 1.3;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.card-meta {
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--ink-muted);
}
.card-sku { font-family: ui-monospace, monospace; }

/* Home categories are intentionally a touch more compact than product rows. */
.category-list { gap: 8px; }
.category-card { padding: 10px 12px; }
.category-card .thumb { width: 48px; height: 48px; }
.category-card .card-name { font-size: 14px; }

.stock-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 600;
  background: var(--ok-bg);
  color: var(--ok);
}
.stock-pill::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
}
.stock-pill.out { background: var(--badge-bg-off); color: var(--badge-ink-off); }

.card-price { flex: none; text-align: right; }
.price-now {
  font-weight: 700;
  font-size: 16px;
  color: var(--accent);
  white-space: nowrap;
}
.price-retail {
  font-size: 11.5px;
  color: var(--ink-faint);
  text-decoration: line-through;
  white-space: nowrap;
}
.price-missing {
  font-size: 12.5px;
  color: var(--ink-faint);
  font-style: italic;
}

.empty {
  text-align: center;
  color: var(--ink-muted);
  padding: 60px 24px;
  font-size: 14px;
}

.orders-empty-banner-link { display: block; margin: 4px 16px 16px; }
.orders-empty-banner {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}

/* ---- Search bar ---- */
.search-bar-wrap { padding: 16px 16px 4px; }
.search-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--card-bg);
  border-radius: var(--radius-pill);
  padding: 11px 14px;
  box-shadow: var(--shadow);
}
.search-icon { flex: none; width: 18px; height: 18px; color: var(--ink-faint); }
.search-bar input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: none;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
}
.search-bar input::placeholder { color: var(--ink-faint); }
.search-clear {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--badge-bg-off);
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  line-height: 1;
}

/* ---- Bottom nav ---- */
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 10;
  background: var(--dark);
  display: flex;
  padding: 8px 4px calc(8px + env(safe-area-inset-bottom));
}
.bottom-nav .tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  color: var(--dark-muted);
  padding: 4px 0;
}
.bottom-nav .tab svg { width: 22px; height: 22px; }
.bottom-nav .tab.active { color: var(--accent); }
.bottom-nav .tab.disabled { opacity: 0.6; }
.tab-icon { position: relative; display: flex; }
.tab-badge {
  position: absolute;
  top: -6px;
  right: -9px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

/* ---- Add-to-cart button on product cards ---- */
.add-form { margin-top: 6px; }
.add-btn {
  width: 30px;
  height: 30px;
  border-radius: 10px;
  border: none;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 18px;
  line-height: 1;
  font-weight: 700;
  cursor: pointer;
}

/* ---- Cart quantity stepper ---- */
.qty-form {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.qty-btn {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  border: none;
  background: var(--badge-bg-off);
  color: var(--ink);
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
}
.qty-value { min-width: 18px; text-align: center; font-weight: 600; font-size: 14px; }

/* ---- Checkout form fields (phone, comment) ---- */
.checkout-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.checkout-form label {
  margin: 0 16px;
  font-size: 12.5px;
  color: var(--ink-muted);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.checkout-form input,
.checkout-form textarea {
  font: inherit;
  font-size: 15px;
  padding: 11px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--card-bg);
  color: var(--ink);
  resize: vertical;
}
.radio-group {
  margin: 0 16px;
  padding: 4px 14px;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}
.radio-group-label {
  margin: 10px 0 2px;
  font-size: 12.5px;
  color: var(--ink-muted);
}
label.radio-option {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 11px 0;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink);
  border-top: 1px solid var(--line);
}
.radio-option:first-of-type { border-top: none; }
.radio-option input[type="radio"] {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
  flex: none;
}

/* ---- Cart summary / checkout ---- */
/* Reuses the home page's promo carousel below the order summary --
   desktop-only (see .cart-layout below), so hidden here by default;
   the template always renders this wrapper when cart_promo_rows is
   non-empty, mobile included, since layout (not content) decides
   visibility. */
.cart-promo-col { display: none; }
.cart-summary {
  margin: 4px 16px 24px;
  padding: 16px;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}
.cart-total-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 12px;
  font-size: 14px;
  color: var(--ink-muted);
}
.cart-total-value { font-size: 20px; font-weight: 700; color: var(--ink); }

/* ---- Account debt ---- */
.account-debt { margin-top: 18px; }
.account-debt-title {
  margin: 0 16px 8px;
  color: var(--ink-muted);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
}
.account-debt-summary {
  min-height: 62px;
  margin: 0 16px;
  padding: 14px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
}
.account-debt-label {
  color: var(--ink-muted);
  font-size: 14px;
  line-height: 1.35;
}
.account-debt-amount {
  flex: none;
  color: var(--ink);
  font-size: 20px;
  line-height: 1.15;
  text-align: right;
}
.account-debt-orders { padding-top: 10px; padding-bottom: 0; }

@media (min-width: 720px) {
  .promo-header h2 { font-size: 14.5px; }
  .account-debt-title { font-size: 13.5px; }
  .account-debt-summary { min-height: 66px; }
}
.primary-btn {
  display: block;
  width: 100%;
  padding: 13px;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}

/* ---- Order confirmation ---- */
.confirm-box { padding: 24px 16px 4px; text-align: center; }
.confirm-icon {
  width: 52px;
  height: 52px;
  margin: 0 auto 12px;
  border-radius: 50%;
  background: var(--ok-bg);
  color: var(--ok);
  font-size: 26px;
  line-height: 52px;
}
.confirm-box h2 { margin: 0 0 12px; }
.confirm-back { margin-top: 12px; }

/* ---- Login page ---- */
.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
}
.login-card {
  width: 100%;
  max-width: 360px;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  padding: 32px 24px;
  box-shadow: var(--shadow);
  text-align: center;
}
.login-wordmark { font-size: 26px; margin-bottom: 4px; }
.login-sub { color: var(--ink-muted); font-size: 13px; margin: 0 0 24px; }
.login-form { display: flex; flex-direction: column; gap: 14px; text-align: left; }
.login-form label { font-size: 12.5px; color: var(--ink-muted); display: flex; flex-direction: column; gap: 6px; }
.login-form input {
  font-size: 15px;
  padding: 11px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink);
}
.login-form .primary-btn { margin-top: 6px; }
.login-hint { margin-top: 18px; font-size: 12px; color: var(--ink-faint); }

/* ---- "Ще" menu rows ---- */
.menu-icon svg { width: 22px; height: 22px; color: var(--badge-ink); }

/* ---- Account page ---- */
.account-avatar {
  width: 88px;
  height: 88px;
  margin: 24px auto 20px;
  border-radius: 50%;
  background: var(--badge-bg);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
}
.account-avatar svg { width: 44px; height: 44px; }
.checkout-form input:disabled {
  color: var(--ink-muted);
  background: var(--bg);
}
.logout-form { margin: 24px 16px 0; }
.logout-btn {
  display: block;
  width: 100%;
  padding: 12px;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--error-bg);
  color: var(--error-ink);
  font-size: 14.5px;
  font-weight: 700;
  cursor: pointer;
}

/* ---- Orders list / detail ---- */
.order-card { align-items: flex-start; }
.order-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 2px;
}
.status-pill {
  flex: none;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.status-pill.new { background: var(--badge-bg); color: var(--badge-ink); }
.status-pill.live { background: var(--ok-bg); color: var(--ok); }

/* ---- Live order accordion (Рахунок/Накладна) ---- */
.order-accordion {
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.order-accordion summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px;
  cursor: pointer;
  list-style: none;
}
.order-accordion summary::-webkit-details-marker { display: none; }
.order-accordion summary .chevron { flex: none; margin-left: 4px; transition: transform 0.15s; }
.order-accordion[open] summary .chevron { transform: rotate(180deg); }
.order-accordion-body { padding: 0 12px 12px; }
.order-line {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  font-size: 13.5px;
  border-top: 1px solid var(--line);
}
.order-doc-buttons { display: flex; gap: 10px; margin-top: 10px; }
.order-doc-buttons a {
  flex: 1;
  text-align: center;
  padding: 10px;
  border-radius: var(--radius-pill);
  background: var(--badge-bg);
  color: var(--badge-ink);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

/* ---- Breadcrumbs (product page) ---- */
.breadcrumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px 16px 0;
  font-size: 12.5px;
  color: var(--ink-muted);
}
.breadcrumbs svg { width: 15px; height: 15px; flex: none; }
.breadcrumbs a { color: var(--ink-muted); text-decoration: underline; }
.breadcrumbs .sep { color: var(--ink-faint); }
.breadcrumbs .current { color: var(--ink); font-weight: 600; }

/* ---- Product page ---- */
.product-photo {
  position: relative;
  margin: 12px 16px 0;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-card);
  background-color: var(--badge-bg);
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--badge-ink);
  font-weight: 700;
  font-size: 32px;
}
.product-photo .thumb-leaf { width: 34%; opacity: 0.55; }
.product-name {
  margin: 16px 16px 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.35;
}
.product-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 14px 16px 0;
}
.product-stat {
  background: var(--card-bg);
  border-radius: 14px;
  padding: 10px 8px;
  text-align: center;
  box-shadow: var(--shadow);
}
.product-stat-label {
  font-size: 10.5px;
  color: var(--ink-muted);
  margin-bottom: 4px;
}
.product-stat-value { font-size: 13.5px; font-weight: 700; }
.product-kv {
  margin: 14px 16px 0;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.product-kv-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  font-size: 13.5px;
  border-top: 1px solid var(--line);
}
.product-kv-row:first-child { border-top: none; }
.product-kv-label { color: var(--ink-muted); }
.product-kv-value {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
  text-align: right;
}
.copy-btn {
  flex: none;
  border: none;
  background: none;
  padding: 2px;
  color: var(--ink-faint);
  display: flex;
  cursor: pointer;
}
.copy-btn svg { width: 15px; height: 15px; }
.copy-btn.copied { color: var(--ok); }
.product-actions { margin: 18px 16px 24px; display: flex; flex-direction: column; gap: 10px; }
.analogs-btn {
  display: block;
  width: 100%;
  padding: 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card-bg);
  color: var(--ink);
  font-size: 14.5px;
  font-weight: 700;
  text-align: center;
}

/* ---- Add-to-cart bottom sheet ---- */
.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: rgba(20, 20, 25, 0.4);
}
.sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 21;
  background: var(--card-bg);
  border-radius: 20px 20px 0 0;
  padding: 10px 16px calc(20px + env(safe-area-inset-bottom));
  box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.12);
}
.sheet-handle {
  width: 36px;
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--line);
  margin: 4px auto 14px;
}
.sheet-product { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.sheet-product .thumb { width: 44px; height: 44px; border-radius: 11px; font-size: 12px; }
.sheet-product-name {
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.3;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.sheet-title { margin: 0 0 10px; font-size: 16px; }
.sheet-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
  font-size: 14px;
}
.stepper { display: flex; align-items: center; gap: 10px; }
.stepper-value { min-width: 20px; text-align: center; font-weight: 700; }
.stepper-btn {
  padding: 8px 12px;
  border: none;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.stepper-btn.minus { background: var(--error-bg); color: var(--error-ink); }
.stepper-btn.plus { background: var(--ok-bg); color: var(--ok); }
.sheet-form { margin-top: 14px; }
.sheet-ok { background: var(--dark); }
.sheet-cancel {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 12px;
  border: none;
  background: none;
  color: var(--ink-muted);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

/* ---- Favorite (heart) toggle ---- */
.fav-form { position: absolute; z-index: 2; }
.fav-btn {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.85);
  color: var(--ink-faint);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow);
}
.fav-btn svg { width: 16px; height: 16px; }
.fav-btn.active { color: var(--error-ink); }

/* Small heart badge over a card's thumb (catalog/search/analogs lists) */
.card { position: relative; }
.card .fav-form { top: 4px; left: 4px; }
.card .fav-btn { width: 22px; height: 22px; }
.card .fav-btn svg { width: 12px; height: 12px; }

/* Larger heart over the product page photo */
.product-photo .fav-form { top: 12px; right: 12px; left: auto; }
.product-photo .fav-btn { width: 40px; height: 40px; }
.product-photo .fav-btn svg { width: 20px; height: 20px; }

/* ---- Muted styling for out-of-stock rows ---- */
.stock-pill.out,
.price-now.muted { color: var(--badge-ink-off); }
.price-now.muted { color: var(--ink-faint); }
.add-btn.muted,
.stepper-btn:disabled,
.primary-btn:disabled {
  background: var(--badge-bg-off);
  color: var(--ink-faint);
  cursor: not-allowed;
}

/* ---- Favorites list ---- */
.fav-header {
  margin: 4px 16px 10px;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.fav-header summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 14px;
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.fav-header summary::-webkit-details-marker { display: none; }
.fav-header summary svg.doc-icon { width: 18px; height: 18px; color: var(--ink-muted); }
.fav-header summary .chevron { width: 18px; height: 18px; margin-left: auto; transition: transform 0.15s; }
.fav-header[open] summary .chevron { transform: rotate(180deg); }

.fav-card { align-items: center; }
.fav-brand { font-size: 11px; letter-spacing: 0.03em; color: var(--ink-muted); text-transform: uppercase; margin-top: 4px; }
.fav-actions { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.fav-status { display: flex; align-items: center; gap: 8px; }
.fav-buttons { display: flex; align-items: center; gap: 8px; }
.fav-remove-btn {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: var(--badge-bg-off);
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.fav-remove-btn svg { width: 15px; height: 15px; }

/* ---- Image lightbox (tap the product photo to view it full-size) ---- */
.product-photo[data-open-image] { cursor: zoom-in; }
.lightbox-backdrop {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: rgba(10, 10, 12, 0.92);
  padding: 24px;
}
/* Only apply flex centering while the backdrop is actually shown — an
   unconditional `display: flex` here would beat the UA stylesheet's
   `[hidden] { display: none }` (author styles always win over UA ones),
   leaving the backdrop visible and intercepting clicks even with the
   hidden attribute set. */
.lightbox-backdrop:not([hidden]) {
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox-img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 12px;
  object-fit: contain;
}
.lightbox-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.lightbox-close svg { width: 20px; height: 20px; }

/* ---- Language picker ---- */
.lang-options {
  margin: 16px 16px 0;
  background: var(--card-bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.lang-option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 15px 16px;
  border: none;
  border-top: 1px solid var(--line);
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 14.5px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.lang-option:first-of-type { border-top: none; }
.lang-option .radio-dot {
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--line);
  position: relative;
}
.lang-option.selected { font-weight: 700; }
.lang-option.selected .radio-dot { border-color: var(--accent); }
.lang-option.selected .radio-dot::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--accent);
}

/* ---- Admin: clients panel ---- */
.admin-search {
  display: flex;
  gap: 8px;
  margin: 12px 16px;
}
.admin-search input {
  flex: 1;
  font: inherit;
  font-size: 15px;
  padding: 11px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--card-bg);
  color: var(--ink);
}
.admin-search-btn {
  flex: none;
  width: 44px;
  border: none;
  border-radius: 10px;
  background: var(--badge-bg);
  color: var(--badge-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.admin-search-btn svg { width: 18px; height: 18px; }
.admin-new-client-btn { margin: 0 16px 14px; width: auto; }
.admin-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: 10px 16px 20px;
}
.admin-pagination-label { font-size: 13px; color: var(--ink-muted); }
.admin-status-row {
  display: flex;
  gap: 8px;
  margin: 4px 16px 18px;
  flex-wrap: wrap;
}
.admin-section { margin-bottom: 22px; }
.admin-section-title {
  margin: 0 16px 8px;
  font-size: 14px;
  font-weight: 700;
}
.admin-danger-btn { background: var(--error-ink); }
.admin-danger-btn:disabled { background: var(--badge-bg-off); color: var(--badge-ink-off); cursor: not-allowed; }
.assistant-settings-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  margin: 8px 0;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--card-bg);
  box-shadow: var(--shadow);
}
.assistant-toggle-btn {
  flex: none;
  border: 0;
  border-radius: var(--radius-pill);
  padding: 9px 13px;
  background: var(--badge-bg);
  color: var(--badge-ink);
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}
.assistant-mode-select {
  font: inherit;
  font-size: 14px;
  padding: 10px 11px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--card-bg);
  color: var(--ink);
  width: 100%;
}
.assistant-pilot-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 4px;
  border-top: 1px solid var(--line);
}
.assistant-pilot-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 13.5px;
}
.assistant-pilot-remove-btn {
  flex: none;
  border: 0;
  border-radius: var(--radius-pill);
  padding: 6px 11px;
  background: var(--badge-bg-off);
  color: var(--badge-ink-off);
  font: inherit;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.admin-checkbox-label {
  flex-direction: row !important;
  align-items: center;
  gap: 8px !important;
  font-size: 13.5px !important;
  color: var(--ink) !important;
}
.checkout-form select {
  font: inherit;
  font-size: 15px;
  padding: 11px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--card-bg);
  color: var(--ink);
}

/* ---- Wider screens: keep it phone-shaped, don't stretch ---- */
@media (min-width: 560px) {
  body {
    max-width: 480px;
    margin: 0 auto;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.06);
    min-height: 100vh;
  }
  .bottom-nav { max-width: 480px; margin: 0 auto; left: 0; right: 0; }
}

/* ---- Desktop (>=1024px): stop capping the layout at phone width, and
   replace the fixed bottom-nav with a persistent left sidebar
   (templates/_sidebar.html). 560-1023px (phone/tablet) is untouched by
   this block -- it keeps the 480px phone-shaped column AND .bottom-nav
   from the rule above exactly as before; .sidebar is a separate
   element included in the same 13 templates as .bottom-nav (plus the
   4 detail pages that only ever had a back-link topbar, no bottom-nav
   at any width) and stays display:none until this breakpoint, so
   nothing about it can affect phone/tablet layout even if a template
   forgets to gate it -- the gating lives here, not per-call. Cascade
   note: both this and the min-width:560px block above match at
   >=1024px; this block comes later in the file, so its rules win for
   body/.bottom-nav at that width without needing !important. */
.sidebar { display: none; }
.product-promo { display: none; }

@media (min-width: 1024px) {
  body { max-width: 1200px; margin-left: 240px; box-shadow: none; }
  .bottom-nav { display: none; }

  .sidebar {
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 240px;
    padding: 20px 16px;
    background: var(--dark);
    overflow-y: auto;
    box-sizing: border-box;
  }
  .sidebar-brand { padding: 0 8px 20px; }
  /* The sidebar's own AGROSPHERA wordmark above already links home, so
     the topbar's copy of the same _brand_home_link.html include (a
     mobile "‹ Back ... AGROSPHERA" pattern) is redundant on any page
     that has a sidebar. Scoped through :has() rather than a blanket
     rule: admin_clients.html/admin_client_new.html/admin_client_detail.html
     deliberately have no sidebar (out of scope for this desktop-layout
     effort) and rely on this exact topbar link as their only way home
     at any width, so their copy must stay visible here. */
  body:has(.sidebar) .topbar .brand-home-link { display: none; }
  /* "Вийти" (categories.html only) moves onto the title's own row, in
     the corner the hidden AGROSPHERA link above just vacated, instead
     of sitting stretched to the opposite edge of a much wider .client-row
     below the title. The client name stays on its own full-width row
     underneath. .client-row itself has no other page reusing it, so
     turning .topbar into a grid here doesn't affect any page that
     lacks it -- .brand alone still fills the "brand" area, and the
     "name"/"logout" areas simply stay empty (auto-sized to 0 height).
     display:contents lets .client-row's own two children (the name
     span and the logout form) become independent grid items of
     .topbar, without touching categories.html's markup at all. */
  .topbar {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "brand  logout"
      "name   logout";
    align-items: center;
    row-gap: 8px;
  }
  .topbar .brand { grid-area: brand; margin-bottom: 0; }
  .client-row { display: contents; font-size: 14.5px; }
  .client-row > span { grid-area: name; }
  /* Spans both rows (rather than just the title's row) so it centers
     vertically against the full topbar block height, not just the
     title's line. */
  .client-row > form { grid-area: logout; align-self: center; }
  .sidebar-links { display: flex; flex-direction: column; gap: 2px; flex: 1; }
  .sidebar-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 8px;
    border-radius: 10px;
    color: var(--dark-muted);
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
  }
  .sidebar-link svg { width: 20px; height: 20px; flex: none; }
  .sidebar-link.active { color: var(--accent); background: rgba(255, 255, 255, 0.08); }
  .sidebar-icon-wrap { position: relative; display: flex; }
  .sidebar-badge {
    position: absolute;
    top: -6px;
    right: -9px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: var(--accent-ink);
    font-size: 10px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
  }
  .sidebar-secondary {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 12px;
    padding: 16px 8px 0;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--dark-muted);
    text-decoration: none;
    font-size: 13px;
  }
  .sidebar-secondary svg { width: 18px; height: 18px; flex: none; }
  .sidebar-secondary.active { color: var(--accent); }

  /* ---- Product/favorites grid (catalog.html, favorites.html,
     search.html) ----
     .list itself is shared by 12 templates for very different content
     (cart lines, order lines, the "Ще" menu, account debt list,
     category rows) -- turning bare .list into a grid would break all
     of those. Scoped via .grid-cards, a modifier class added ONLY to
     the 3 templates that actually render a product-card list;
     categories.html's .category-list deliberately stays a plain row
     list, out of this step's scope. Card-internal reflow (thumb on
     top instead of thumb beside body) covers both card shapes used
     here: catalog/search's plain .card (.card-link + .card-price/
     .add-form) and favorites' .card.fav-card (.card-link +
     .fav-actions/.fav-status/.fav-buttons). No template markup beyond
     the .grid-cards class itself changed -- every element reflowed
     below already existed. */
  .grid-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 16px;
  }
  .grid-cards .card { flex-direction: column; align-items: stretch; gap: 10px; }
  .grid-cards .card-link { flex-direction: column; align-items: stretch; gap: 10px; }
  .grid-cards .thumb { width: 100%; height: auto; aspect-ratio: 1 / 1; }
  .grid-cards .card-price { text-align: left; margin-top: 4px; }
  .grid-cards .add-form { width: 100%; margin-top: 8px; }
  .grid-cards .add-btn { display: block; width: 100%; height: 36px; border-radius: var(--radius-pill); font-size: 20px; }
  .grid-cards .fav-actions { align-items: stretch; margin-top: 4px; }
  .grid-cards .fav-status { justify-content: space-between; }
  .grid-cards .fav-buttons { justify-content: flex-end; }

  /* ---- Home page (categories.html) ----
     .home-banner needs no rule here: it's a plain <img> (height:auto,
     no object-fit crop) so it already scales without distortion, and
     the native asset is 1200x409 -- body's own max-width:1200px above
     means the rendered width never exceeds that, so it never upscales
     past source resolution either. Only .category-list and the "Акції
     та новинки" carousel actually still looked mobile-narrow at this
     breakpoint; both keep their exact markup, data and hrefs from
     categories.html, reflowed the same specificity-override way as
     .grid-cards above. */
  .category-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 12px;
  }
  .category-list .category-card { padding: 14px 16px; }
  .category-list .category-card .thumb { width: 56px; height: 56px; font-size: 15px; }
  .category-list .category-card .card-name { font-size: 15px; }

  /* promo-carousel.js measures the actual rendered gap between the
     first two cards to compute its scroll step, so a narrower fixed
     card width is all this needs -- arrows/dots/drag/scroll-snap keep
     working unchanged, just revealing more cards per screen instead of
     the mobile ~44%-width, ~2-cards-plus-a-peek layout. */
  .promo-card { width: 200px; }

  /* ---- Product page (product.html): photo left / info right ----
     .product-layout/.product-photo-col/.product-info-col are new
     wrapper elements (template still renders the exact same
     .product-photo/.product-name/.product-stats/.product-kv/
     .product-actions markup, same data, same fav/add-to-cart forms --
     just grouped so they can become two flex/grid columns here). Below
     1024px these wrappers carry no rules at all, so the mobile stack
     is byte-identical to before: block-level children with their own
     margins collapse through a plain, unstyled parent div exactly as
     if there were no wrapper.
     minmax(0, 1fr) on the second column (not a bare 1fr) is
     deliberate: a bare 1fr's implicit min-width is its content's
     min-content, which for a long, unbreakable product name would
     force the whole grid wider than its container -- exactly the
     horizontal-scroll bug this must avoid. minmax(0, 1fr) lets the
     column shrink below that and wrap text instead.
     Photo column capped at 340px (was 420px) -- the row data has no
     description/specs/reviews field to give the info column (see
     catalog.py's row dict: sku/name/brand/stock/price/category/image,
     nothing else), so a wide photo column just pushed a thin info
     column next to a lot of leftover vertical space under both. A
     narrower photo shortens that empty area instead of trying to
     paper over it with invented copy or stretched blocks. */
  .product-layout {
    display: grid;
    grid-template-columns: minmax(220px, 340px) minmax(0, 1fr);
    align-items: start;
    gap: 32px;
    margin: 12px 16px 24px;
  }
  .product-photo-col .product-photo { margin: 0; }
  .product-info-col .product-name { margin: 0; font-size: 26px; line-height: 1.25; }
  .product-info-col .product-stats { margin: 20px 0 0; }
  /* Same .product-stats grid/.product-stat card as every breakpoint --
     only the price cell's own value gets emphasized, via the modifier
     class product.html already adds to just that one cell, reusing
     the same accent color .price-now uses everywhere else on the
     site for a wholesale price. */
  .product-info-col .product-stat-price .product-stat-value {
    color: var(--accent);
    font-size: 20px;
  }
  .product-info-col .product-kv { margin: 16px 0 0; }
  /* Row instead of the mobile column stack, and no width cap: with the
     .recommended block gone (see .product-promo below) this is the
     only content the info column's own leftover width would otherwise
     go to waste on. .analogs-btn (conditionally rendered) keeps its
     ~35% share via flex-basis; .add-form/.primary-btn grow into
     whatever's left -- 100% of the row when there's no analogs button
     at all, since flex:1 1 auto is the only item then. */
  .product-info-col .product-actions {
    margin: 20px 0 0;
    flex-direction: row;
    align-items: stretch;
  }
  .product-info-col .product-actions .analogs-btn { flex: 0 1 35%; width: auto; }
  .product-info-col .product-actions .add-form { flex: 1 1 auto; margin: 0; }
  .product-info-col .product-actions .add-form .primary-btn { height: 100%; }

  /* ---- "Акції та новинки" on product.html ----
     A sibling of .product-layout, not nested inside either of its
     columns, so it can never stretch the photo/info grid's own height
     and always spans the full content width next to the sidebar.
     Reuses the exact same _promo_carousel.html partial/macro as the
     home page and cart.html -- same promo_rows source (isSale/isNew),
     same cards/badges/prices/favorites/add-to-cart/arrows/dots/drag,
     just with the current product's own SKU excluded (main.py) so it
     never recommends itself. .product-promo is the page-specific,
     display:none-by-default wrapper (base rule above) that used to
     gate the old "Рекомендовані товари" block the same way; the
     shared .promo-carousel itself carries no such gate since the home
     page needs it visible on mobile too.
     margin-top here is deliberately smaller than the photo/info
     block's own 24px bottom margin would suggest (12px, not 32px) --
     .promo-carousel's own 6px top margin (zeroed below) and header
     padding already read as enough separation without stacking a
     second, larger gap on top of it. */
  .product-promo { display: block; margin: 12px 16px 0; }
  .product-promo .promo-carousel { margin-top: 0; }

  /* ---- Cart / checkout (cart.html): one column of items+fields, a
     sticky order-summary sidebar on the right ----
     Still exactly ONE <form class="checkout-form">, same CSRF/
     idempotency hidden inputs, same field names, same /checkout route
     -- nothing here duplicates the form or the submit button.
     .checkout-form is given display:contents here (desktop only):
     the <form> element itself stops generating a box, but stays the
     real form its descendant inputs submit through, and its direct
     children (the phone label, both .radio-group blocks, the comment
     label, .cart-summary) become individually placed items of the
     OUTER .cart-layout grid below -- the only way to get "form fields
     in the left column, submit/total in a right sidebar" without a
     second <form> or copying the submit button. Child combinators
     (.cart-layout > .checkout-form > ...) still work fine under
     display:contents -- it changes box generation, not the DOM or
     selector matching.
     .checkout-field-phone/-delivery/-payment/-comment are the only
     new classes added to the template, purely as grid-area hooks --
     same elements, same attributes otherwise.
     grid-template-areas gives "summary" one rectangular cell spanning
     all 5 left-column rows (items/phone/delivery/payment/comment) by
     construction, so .cart-summary's sticky positioning has a
     well-defined height to stick within -- once the viewport scrolls
     past the bottom of that 5-row span, it scrolls away with the rest
     instead of sticking over content below (never over the sidebar/
     assistant widget/whatever follows). Row count is fixed regardless
     of 1 vs many cart lines: .list is a single grid item no matter how
     many .card children it holds, so this layout doesn't change shape
     with cart size. minmax(0, 1fr) on the items column (not a bare
     1fr) is a deliberate overflow guard: a bare 1fr's implicit
     min-width is its content's min-content, and a long, unbreakable
     product name in a cart line could otherwise force the grid wider
     than its container -- the same fix already used for
     .product-layout's info column. */
  .cart-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(260px, 360px);
    grid-template-areas:
      "items    summary"
      "phone    summary"
      "delivery summary"
      "payment  summary"
      "comment  summary";
    align-items: start;
    gap: 20px 32px;
    margin: 12px 16px 24px;
  }
  .cart-items-col { grid-area: items; }
  .cart-items-col .list { padding: 0; }
  /* Scoped to .cart-layout specifically -- .checkout-form is also
     reused (as a generic vertical-form style, unrelated markup) by
     account.html and the out-of-scope admin_client_*.html pages; a
     bare .checkout-form rule here would have flattened their forms
     into unstyled loose grid/flex items too. */
  .cart-layout > .checkout-form { display: contents; }
  .cart-layout > .checkout-form > .checkout-field-phone { grid-area: phone; margin: 0; }
  .cart-layout > .checkout-form > .checkout-field-delivery { grid-area: delivery; margin: 0; }
  .cart-layout > .checkout-form > .checkout-field-payment { grid-area: payment; margin: 0; }
  .cart-layout > .checkout-form > .checkout-field-comment { grid-area: comment; margin: 0; }
  /* Sticky within the 5-row span above -- topbar is itself
     `position:sticky; top:0`, so this offset (its rendered height plus
     a little breathing room) keeps the summary from sliding under it. */
  .cart-layout > .checkout-form > .cart-summary {
    grid-area: summary;
    margin: 0;
    position: sticky;
    top: 88px;
    align-self: start;
  }

  /* "Акції та новинки" reused verbatim (same promo_rows source, same
     _promo_carousel.html partial, same JS) directly under the order
     summary in the right column -- see .cart-promo-col's base rule
     above for why it's hidden outside this media block.
     Deliberately given the SAME grid-area as .cart-summary (both
     "summary") rather than a row of its own: a row of its own would
     have to start only after row 1-5's full height, which is set by
     the LEFT column's (much taller) items/phone/delivery/payment/
     comment content -- leaving a large empty gap under the compact
     summary card and burying this carousel until the visitor has
     scrolled all the way past the checkout form. Sharing the area
     instead means both sit within the same tall sticky-capable cell;
     margin-top pushes this one down to sit right under the summary
     card's own fixed content height (one total row + one button, so
     it doesn't vary with cart size), and its own `top` offset is that
     same amount added to the summary's `top:88px` -- so as the page
     scrolls, both remain visible together directly under the topbar
     instead of only appearing once fully scrolled past the form, and
     both scroll away together once past the row 1-5 span (never
     overlapping the footer/assistant below).
     .promo-card's existing 200px desktop width (see .category-list
     rules above) already fits this narrow ~260-360px column showing
     one full card plus a peek of the next -- no override needed here,
     and the carousel's own .promo-track overflow-x:auto keeps any
     scrolling local to the track, never the page. */
  .cart-promo-col {
    display: block;
    grid-area: summary;
    align-self: start;
    margin: 135px 0 0;
    position: sticky;
    top: 223px;
  }
  .cart-promo-col .promo-carousel { margin-top: 0; }
  .cart-promo-col .promo-header,
  .cart-promo-col .promo-track,
  .cart-promo-col .promo-dots { margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0; }
}

/* ---- Offline banner (static/offline-banner.js toggles [hidden] from
   navigator.onLine / online / offline -- no page state, no user data).
   Deliberately a normal in-flow block, NOT position:fixed/sticky: this
   file's .topbar is already `position: sticky; top: 0` (see above), and
   a fixed banner at top:0 would float ON TOP of the topbar's title/logo
   instead of pushing it down -- confirmed visually with a Playwright
   screenshot before landing this. Being the first element in <body>
   (every template includes it right after the opening tag) means it
   simply reserves its own space above the topbar when shown, with zero
   overlap risk against anything -- the bottom nav, the add-to-cart
   sheet and the assistant mascot are all bottom-anchored and never
   share space with this regardless. The one cost is that it scrolls
   away with the rest of the page instead of staying pinned -- an
   acceptable trade for a connectivity notice. See .lightbox-backdrop
   above for why the flex layout is scoped to :not([hidden]) instead of
   set unconditionally. ---- */
.offline-banner {
  background: var(--warn-bg);
  color: var(--warn-ink);
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  padding: 8px 16px;
  padding-top: calc(8px + env(safe-area-inset-top));
}
.offline-banner:not([hidden]) {
  display: flex;
  align-items: center;
  justify-content: center;
}
.offline-banner[hidden] { display: none; }
/* .login-body is itself `display:flex` (row, centered) with no
   .topbar sibling to protect against -- left in normal flow there,
   the banner would become a flex item and get squeezed/centered next
   to .login-card instead of spanning full width above it (confirmed
   visually with a Playwright screenshot). Nothing on this page sits
   at the very top to overlap, so position:fixed is safe here and
   also removes it from login-body's flex layout entirely. */
.login-body .offline-banner:not([hidden]) {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
}

/* ---- Hover / keyboard-focus affordances ----
   The site had almost no :hover feedback and only one :focus-visible
   rule anywhere (.brand-home-link, above) -- fine for a touch-first
   mobile layout, but a real gap for the desktop mouse/keyboard
   audience this branch targets. Pure visual feedback: no size,
   layout, or behavior change to any element below.
   a.card covers categories.html's whole-card links; .card-link covers
   catalog/search/favorites/cart's separate product-row link (their
   outer .card is a plain, non-clickable wrapper div, so it's
   deliberately left out here).
   .promo-arrow/.promo-dot are scoped through .promo-carousel
   specifically so admin_clients.html's unrelated pagination controls
   (which reuse the same two class names) are left untouched, per this
   branch's standing admin-pages exclusion. */
.sidebar-link:hover { background: rgba(255, 255, 255, 0.05); }
a.card:hover,
.category-card:hover { box-shadow: 0 4px 16px rgba(20, 20, 25, 0.1); }
.card-link:hover .card-name { color: var(--accent); }
.qty-btn:hover { background: var(--badge-bg); }
.fav-btn:hover,
.add-btn:hover,
.primary-btn:hover { filter: brightness(0.94); }
.link-btn:hover { color: var(--accent); }
.back-link:hover svg { color: var(--accent); }
.radio-option:hover { background: var(--badge-bg); }
.promo-carousel .promo-arrow:hover { background: var(--accent); color: var(--accent-ink); }
.promo-carousel .promo-dot:hover { background: var(--accent); }

.sidebar-link:focus-visible,
a.card:focus-visible,
.card-link:focus-visible,
.category-card:focus-visible,
.qty-btn:focus-visible,
.fav-btn:focus-visible,
.add-btn:focus-visible,
.primary-btn:focus-visible,
.link-btn:focus-visible,
.back-link:focus-visible,
.radio-option input[type="radio"]:focus-visible,
.search-bar input:focus-visible,
.promo-carousel .promo-arrow:focus-visible,
.promo-carousel .promo-dot:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
