/* ==========================================================================
   TurbonX BD — Page-specific styles: product detail + checkout
   ========================================================================== */

/* --- Breadcrumb --------------------------------------------------------- */
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding-block: var(--sp-5) 0;
  font-size: var(--step--2);
  color: var(--text-tertiary);
}
.breadcrumb a { color: var(--text-secondary); transition: color var(--dur-2) var(--ease-out); }
.breadcrumb a:hover { color: var(--text-primary); }
.breadcrumb__sep { opacity: 0.5; }
.breadcrumb [aria-current] { color: var(--text-primary); }

/* --- Product detail --------------------------------------------------- */
.pdp {
  display: grid;
  gap: clamp(2rem, 1rem + 5vw, 4rem);
  padding-block: var(--sp-6) var(--sp-9);
}
/* The generous gap above is meant for the two-column desktop layout
   (image | info, side by side) — stacked on mobile it read as a wall of
   empty space between the gallery and the product name. */
@media (max-width: 899px) { .pdp { gap: var(--sp-4); } }
@media (min-width: 900px) { .pdp { grid-template-columns: 1.05fr 0.95fr; align-items: start; } }

.pdp__gallery { display: grid; gap: var(--sp-3); }
@media (min-width: 560px) { .pdp__gallery { grid-template-columns: 72px 1fr; } }
@media (min-width: 900px) { .pdp__gallery { position: sticky; top: calc(var(--header-h) + var(--sp-4)); } }

.pdp__stage {
  position: relative;
  aspect-ratio: 1 / 1;
  /* --bg-primary, not --media-bg — see .product-card__media's own comment
     in components.css: a transparent (background-removed) product photo
     should blend into the page's own light/dark background, not a fixed
     grey well. */
  background: var(--bg-primary);
  border: 1px solid var(--border-faint);
  border-radius: var(--r-lg);
  overflow: hidden;
  order: 1;
  touch-action: pan-y;            /* let vertical page scroll through, we own the x */
}
@media (min-width: 560px) { .pdp__stage { order: 2; } }

.pdp__stage-track {
  display: flex;
  width: 100%; height: 100%;
  will-change: transform;
  transition: transform var(--dur-3) var(--ease-out);
}
.pdp__stage-track.is-dragging { transition: none; }
.pdp__slide { flex: 0 0 100%; height: 100%; position: relative; }
.pdp__slide img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* base.css gives every <img> a --media-bg (fixed light-grey) background
     by default — that sits right on top of .pdp__stage's own background
     and would otherwise be the thing actually showing through a
     transparent PNG, not the stage. Transparent here lets the stage's
     --bg-primary (white/black, theme-matched) show through instead. */
  background: transparent;
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;          /* drags land on the track, taps go through to nav/dots */
  transition: transform 0.2s ease-out;
}

/* prev / next — same glass-pill language as the homepage offer banner */
.pdp__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  color: var(--text-primary);
  background: color-mix(in srgb, var(--bg-primary) 82%, transparent);
  backdrop-filter: blur(12px) saturate(1.4);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  opacity: 0.65;
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-1) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.pdp__stage:focus-within .pdp__nav { opacity: 1; }
@media (hover: hover) {
  .pdp__stage:hover .pdp__nav { opacity: 1; }
  .pdp__nav:hover { background: var(--bg-primary); opacity: 1; }
}
.pdp__nav:active { transform: translateY(-50%) scale(0.9); }
.pdp__nav svg { width: 17px; height: 17px; }
.pdp__nav--prev { left: var(--sp-3); }
.pdp__nav--next { right: var(--sp-3); }
@media (hover: none) { .pdp__nav { opacity: 0.9; } }

.pdp__dots {
  position: absolute;
  left: 50%; bottom: var(--sp-3);
  transform: translateX(-50%);
  z-index: 2;
  display: flex; align-items: center; gap: 6px;
  padding: 6px 9px;
  border-radius: var(--r-pill);
  background: rgba(10, 10, 10, 0.42);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.pdp__dot { width: 6px; height: 6px; border-radius: var(--r-pill); background: #fff; opacity: 0.5; transition: opacity var(--dur-2) var(--ease-out), width var(--dur-2) var(--ease-out); }
.pdp__dot.is-active { opacity: 1; width: 16px; }
@media (prefers-reduced-motion: reduce) { .pdp__stage-track { transition: none; } }

.pdp__thumbs {
  display: flex;
  gap: var(--sp-2);
  order: 2;
  overflow-x: auto;
  scrollbar-width: none;
}
.pdp__thumbs::-webkit-scrollbar { display: none; }
@media (min-width: 560px) { .pdp__thumbs { flex-direction: column; order: 1; overflow: visible; } }
.pdp__thumb {
  flex: 0 0 auto;
  width: 64px;
  aspect-ratio: 1;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--bg-primary);
  object-fit: cover;
  opacity: 0.5;
  transition: opacity var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
@media (min-width: 560px) { .pdp__thumb { width: 100%; } }
.pdp__thumb.is-active { opacity: 1; border-color: var(--text-primary); }

.pdp__info { display: grid; gap: var(--sp-4); align-content: start; }
.pdp__eyebrow { font-size: var(--step--2); color: var(--text-tertiary); }
/* Name, short description and price read as one tight block (their own
   small gap) — .pdp__info's wider gap picks back up after this group, for
   the divider/variants/buy box below. */
.pdp__headline { display: grid; gap: var(--sp-1); }
.pdp__name {
  font-size: var(--step-3); font-weight: 800; letter-spacing: -0.03em; line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  /* fitTitle() (page.product.js) shrinks this further, on one line, for a
     name too long even at this size — the ellipsis here is only a fallback
     for the rare name still too long at that function's own size floor. */
}
.pdp__brand { font-size: var(--step--1); color: var(--text-tertiary); }
/* own-brand lockup: mirrors the header wordmark (bold "TurbonX" + small "BD"
   badge) instead of plain text, so it reads as the actual brand mark rather
   than a generic "by X" caption. A third-party p.brand just prints as-is. */
.pdp__brand--own {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3em;
}
.pdp__brand-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 125%;
  font-size: var(--step-0);
  letter-spacing: -0.03em;
  color: var(--text-primary);
}
.pdp__price { display: flex; align-items: baseline; gap: 0.6em; flex-wrap: wrap; }
.pdp__price .price__now { font-size: var(--step-2); }
/* Picking a variant with its own price rebuilds this block fresh each
   time (see render() in page.product.js) — every child here is a brand
   new element on every click, so a plain CSS entrance animation just
   replays automatically, no JS retrigger needed. The "was" price's line-
   through draws across it a beat after the number appears, instead of
   the price just instantly snapping to its struck-through/shrunk state. */
.pdp__price .price__now { animation: pdpPriceIn 0.3s var(--ease-out); }
.pdp__price .price__was { position: relative; text-decoration: none; animation: pdpPriceIn 0.3s var(--ease-out) 0.05s both; }
/* A slight diagonal slash (bottom-left to top-right), not a flat
   horizontal strikethrough — transform-origin stays on the LEFT edge
   (which never moves) so the grow-across animation rotates cleanly around
   that fixed point instead of swivelling around a center that's itself
   shifting as the line's width animates. */
.pdp__price .price__was::after {
  content: ""; position: absolute; left: 0; right: 100%; top: 68%; height: 1px; background: currentColor;
  transform-origin: left center; transform: rotate(-10deg);
  animation: pdpStrike 0.22s var(--ease-out) 0.22s forwards;
}
.pdp__price .price__off { animation: pdpPriceIn 0.3s var(--ease-out) 0.15s both; }
@keyframes pdpPriceIn { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }
@keyframes pdpStrike { to { right: 0; } }
@media (prefers-reduced-motion: reduce) {
  .pdp__price .price__now, .pdp__price .price__was, .pdp__price .price__off { animation: none; }
  .pdp__price .price__was { text-decoration: line-through; }
  .pdp__price .price__was::after { display: none; }
}
.pdp__desc-wrap { position: relative; }
/* Clamped to 2 lines by default — .pdp__desc-more only exists in the DOM
   (and only shows) when the text actually overflows that, see
   wireDescMore() in page.product.js. It sits pinned to the bottom-right
   corner of the clamped text (not stacked as its own row below it) —
   reads as an inline "...More" at the end of line 2, and doesn't add any
   extra height/gap before the price under it. */
.pdp__desc { color: var(--text-secondary); font-size: var(--step-0); max-width: 52ch; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; padding-right: 2.6em; }
.pdp__desc.is-expanded { -webkit-line-clamp: unset; overflow: visible; padding-right: 0; }
.pdp__desc-more {
  position: absolute; right: 0; bottom: 0;
  font-size: var(--step--2); font-weight: 700; color: var(--text-tertiary);
  text-decoration: underline; text-underline-offset: 2px;
  background: var(--bg-primary); padding-left: 6px;
}
/* Expanded: the button drops out of the corner and just sits after the
   now-full text, in normal flow, like an ordinary trailing link. */
.pdp__desc.is-expanded ~ .pdp__desc-more { position: static; display: inline-block; margin-top: 2px; padding-left: 0; background: none; }
@media (hover: hover) { .pdp__desc-more:hover { color: var(--text-primary); } }
/* No margin of its own — .pdp__info's own grid gap already puts space on
   both sides of it; an extra margin here was doubling that up into a much
   bigger gap than the rest of the page's spacing rhythm. */
.pdp__divider { height: 1px; background: var(--border-faint); }
/* Mirrors the gallery/info split visually on mobile, where they're stacked
   (one column) instead of side by side — not needed once the two-column
   desktop layout kicks in, since the gallery sits beside the info there,
   not above it. */
@media (min-width: 900px) { .pdp__divider--top { display: none; } }

.pdp__variants { display: grid; gap: var(--sp-4); }

/* --- Multi-select variant picker: several colours, sizes within each --- */
.pdp__multi-rows { display: grid; gap: var(--sp-3); }
.pdp__multi-row {
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--border-faint);
  border-radius: var(--r-sm);
  background: var(--surface);
}
.pdp__multi-row-head { display: flex; align-items: center; gap: var(--sp-2); }
.pdp__multi-row-head strong { font-size: var(--step--1); }
.pdp__multi-row-stock { font-size: var(--step--2); color: var(--text-tertiary); margin-inline-start: auto; }
.pdp__multi-remove {
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  color: var(--text-tertiary);
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
@media (hover: hover) { .pdp__multi-remove:hover { background: var(--surface-sunken); color: var(--danger); } }
.pdp__multi-remove svg { width: 12px; height: 12px; }

.pdp__buy { display: grid; gap: var(--sp-3); }
.pdp__buy-row { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.pdp__buy-row .qty { flex-shrink: 0; }
.pdp__buy-row .btn { flex: 1; min-width: 160px; }
.pdp__meta { display: grid; gap: 6px; font-size: var(--step--2); color: var(--text-tertiary); }
.pdp__meta div { display: flex; gap: 8px; }
.pdp__meta dt { color: var(--text-tertiary); min-width: 88px; }
.pdp__meta dd { color: var(--text-secondary); }

/* --- Tabs (description / specs / reviews) ------------------------- */
.pdp-tabs { padding-bottom: var(--sp-9); }
.pdp-tabs__list {
  display: flex;
  gap: var(--sp-2);
  border-bottom: 1px solid var(--border-faint);
  overflow-x: auto;
  scrollbar-width: none;
}
.pdp-tabs__list::-webkit-scrollbar { display: none; }
.pdp-tabs__tab {
  position: relative;
  padding: var(--sp-3) var(--sp-2);
  font-size: var(--step-0);
  font-weight: 600;
  color: var(--text-tertiary);
  white-space: nowrap;
  transition: color var(--dur-2) var(--ease-out);
}
.pdp-tabs__tab[aria-selected="true"] { color: var(--text-primary); }
.pdp-tabs__tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: var(--sp-2); right: var(--sp-2); bottom: -1px;
  height: 2px;
  background: var(--text-primary);
}
.pdp-tabs__panel { padding-top: var(--sp-6); max-width: 68ch; }
.pdp-tabs__panel p { color: var(--text-secondary); }

/* --- Long-form rich text: product long descriptions (data.products.js)
   AND the info-page documents (About/FAQ/Shipping/Returns/Privacy/Terms —
   see page.info.js) share this same block. Headings, images and lists all
   get the site's own type scale so any arbitrarily long write-up still
   reads like part of the same page, whichever of the two renders it. */
.pdp-longdesc, .info-doc { display: grid; gap: var(--sp-4); }
.pdp-longdesc h2, .info-doc h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 115%;
  font-size: var(--step-2);
  letter-spacing: -0.01em;
  color: var(--text-primary);
}
.pdp-longdesc h3, .info-doc h3 { font-size: var(--step-1); font-weight: 700; color: var(--text-primary); }
.pdp-longdesc p, .info-doc p { color: var(--text-secondary); line-height: 1.65; }
.pdp-longdesc ul, .pdp-longdesc ol, .info-doc ul, .info-doc ol { padding-inline-start: 1.25em; color: var(--text-secondary); display: grid; gap: 6px; }
.pdp-longdesc strong, .info-doc strong { color: var(--text-primary); font-weight: 700; }
.pdp-longdesc blockquote, .info-doc blockquote {
  margin: 0;
  padding-inline-start: var(--sp-4);
  border-left: 3px solid var(--border-strong);
  font-size: var(--step-0);
  color: var(--text-secondary);
  font-style: italic;
}
.pdp-longdesc img, .info-doc img {
  width: 100%;
  border-radius: var(--r-md);
  background: var(--media-bg);
  display: block;
}
:root[lang="bn"] .pdp-longdesc h2, :root[lang="bn"] .info-doc h2,
:root[lang="bn"] .pdp-longdesc h3, :root[lang="bn"] .info-doc h3 { font-family: var(--font-bangla); font-stretch: normal; letter-spacing: 0; }
/* Website content (Admin → Website content, a visual editor): whatever the admin wrote — lists, links, pictures, lines */
.info-doc ul { list-style: disc; } .info-doc ol { list-style: decimal; }
.info-doc h4 { font-size: var(--step-0); font-weight: 700; color: var(--text-primary); }
.info-doc a, .faq-item__a a { color: var(--text-primary); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.info-doc a:hover, .faq-item__a a:hover { text-decoration-thickness: 2px; }
.info-doc hr { border: 0; border-top: 1px solid var(--border-faint); margin: var(--sp-2) 0; }
.info-doc--rich img { width: auto; max-width: 100%; height: auto; background: transparent; }
.info-doc u { text-underline-offset: 3px; }
.faq-item__a { display: grid; gap: var(--sp-2); margin-top: var(--sp-3); color: var(--text-secondary); line-height: 1.6; }
.faq-item .faq-item__a p { margin-top: 0; }
.faq-item__a ul, .faq-item__a ol { padding-inline-start: 1.25em; display: grid; gap: 4px; }
.faq-item__a ul { list-style: disc; } .faq-item__a ol { list-style: decimal; }
.faq-item__a img { max-width: 100%; height: auto; border-radius: var(--r-md); }
.faq-item summary strong, .faq-item summary b { font-weight: inherit; }

.spec-table { width: 100%; border-collapse: collapse; }
.spec-table th,
.spec-table td { text-align: left; padding: var(--sp-3) 0; border-bottom: 1px solid var(--border-faint); font-size: var(--step--1); vertical-align: top; }
.spec-table th { color: var(--text-tertiary); font-weight: 500; width: 40%; }
.spec-table td { color: var(--text-primary); }

.reviews__head { display: flex; align-items: baseline; gap: var(--sp-4); margin-bottom: var(--sp-5); }
.reviews__score { font-family: var(--font-display); font-stretch: 125%; font-weight: 800; font-size: var(--step-4); }
.review { padding-block: var(--sp-4); border-bottom: 1px solid var(--border-faint); }
.review__top { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3); }
.review__name { font-weight: 600; font-size: var(--step--1); }
.review__stars { display: inline-flex; color: var(--text-primary); }
.review__stars svg { width: 13px; height: 13px; }
.review__date { font-size: var(--step--2); color: var(--text-tertiary); }
.review__body { margin-top: var(--sp-2); color: var(--text-secondary); font-size: var(--step--1); }

.related { padding-bottom: var(--sp-9); }

/* --- Checkout -------------------------------------------------- */
.checkout {
  display: grid;
  gap: clamp(2rem, 1rem + 4vw, 3.5rem);
  padding-block: var(--sp-6) var(--sp-9);
}
/* Near half-half, summary kept a touch bigger since it's the side that's
   actually giving information (price breakdown) rather than collecting it.
   Explicit areas (not source order) place the 4 direct children — contact/
   delivery/payment stacked left, #co-summary spanning the right column —
   because on mobile those same 4 children fall back to plain DOM order
   (contact, delivery, summary, payment), which is the order the summary
   needs to land BEFORE payment there. Don't reintroduce a wrapping <form>
   around contact/delivery/payment — that would put summary back after all
   three on mobile. */
@media (min-width: 940px) {
  .checkout {
    grid-template-columns: 0.95fr 1.05fr;
    grid-template-areas: "contact summary" "delivery summary" "payment summary";
    /* stretch (not start): #co-summary spans all 3 rows, so this is what
       makes it reach exactly as far down as Payment's own bottom edge —
       align-items:start would only let it be as tall as its own content. */
    align-items: stretch;
  }
  .checkout__contact { grid-area: contact; }
  .checkout__delivery { grid-area: delivery; }
  .checkout__payment { grid-area: payment; }
  #co-summary { grid-area: summary; }
  /* max-height (not height) — the card should hug its own content and
     grow taller as products are added, same as it always did, just now
     capped at Payment's own bottom edge instead of an arbitrary rem
     value. A flat height:100% here was tried first and was wrong: with
     few products it forced the card (and therefore #co-lines, its flex
     child below) to always fill that full height regardless of actual
     content, and an auto-rows CSS Grid stretches its rows to soak up
     exactly that kind of leftover space by default — the reported
     "options got huge" bug was that stretch, not any size value actually
     being changed on the rows themselves. A plain max-height:100% doesn't
     work here either, even just as a cap: #co-summary spans the same 3
     rows as Contact/Delivery/Payment, so 100% resolves against a height
     that itself grows to fit this card's own content — circular. The
     real cap is set as a plain px value by page.checkout.js's
     syncSummaryHeight(), measuring the left column directly; this
     max-height:none is only what's in effect before that JS runs.
     Selector is #co-summary .order-summary, not just .order-summary —
     same equal-specificity-loses-to-source-order trap as #co-lines
     above: the base rule (line ~424) also sets display, and appears
     later in the file, so a bare .order-summary here would silently stay
     display:grid at 940px+ and every flex property below would be inert
     (this is exactly what happened the first time — #co-lines never
     actually shrank because its "flex-shrink" was being applied inside a
     still-display:grid container). */
  #co-summary .order-summary { display: flex; flex-direction: column; max-height: none; }
  /* Only #co-lines may compress once the card above hits its cap — every
     other child keeps flex-shrink:0 so a long list scrolls internally
     instead of squeezing the title/button/coupon/totals around it. */
  #co-summary .order-summary__title, #co-summary .order-add-toggle, #co-summary .coupon-row, #co-summary .field__error, #co-summary .order-totals { flex-shrink: 0; }
  /* #co-lines, not .order-lines — the base rule below (line ~449) sets
     the same properties at equal specificity and appears LATER in the
     file, so on a tie it would silently win over this media-query block
     regardless of viewport width. The id bumps specificity so this
     override actually takes effect at 940px+ instead of being shadowed
     back down to the mobile 26rem cap. */
  #co-lines { flex: 0 1 auto; min-height: 0; max-height: none; align-content: start; }
}

.checkout__steps {
  display: flex;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
  font-size: var(--step--2);
  color: var(--text-tertiary);
  flex-wrap: wrap;
}
.checkout__step { display: flex; align-items: center; gap: 8px; }
.checkout__step-num {
  width: 22px; height: 22px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: 700;
}
.checkout__step.is-active { color: var(--text-primary); }
.checkout__step.is-active .checkout__step-num { background: var(--text-primary); color: var(--bg-primary); border-color: var(--text-primary); }

.checkout__form { display: grid; gap: var(--sp-6); }
.form-section { display: grid; gap: var(--sp-4); }
.form-section__title { font-size: var(--step-1); font-weight: 700; letter-spacing: var(--tracking-tight); }
.form-row { display: grid; gap: var(--sp-4); }
/* align-items:start (not the grid default stretch) — otherwise one field
   having a hint line (Phone) and its neighbour not (Email) stretches both
   .field boxes to the same height, and left the shorter one free to drift
   instead of its input lining up with the other one's. */
@media (min-width: 560px) { .form-row--2 { grid-template-columns: 1fr 1fr; align-items: start; } }

.radio-card {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
@media (hover: hover) { .radio-card:hover { border-color: var(--text-primary); } }
.radio-card:has(input:checked) { border-color: var(--text-primary); background: var(--surface-sunken); }
.radio-card input { margin-top: 3px; accent-color: var(--text-primary); }
.radio-card__title { font-weight: 600; font-size: var(--step--1); }
.radio-card__note { font-size: var(--step--2); color: var(--text-tertiary); }

.order-summary {
  position: sticky;
  top: calc(var(--header-h) + var(--sp-4));
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.order-summary__title { font-size: var(--step-0); font-weight: 700; }
/* Internally scrollable so adding many products can't grow the whole card
   — only the line list scrolls; title, add-product, coupon and totals
   stay put below it. This 26rem cap is the mobile/default fallback (no
   taller left column to match there); ≥940px replaces it with flex:1 (see
   .checkout above) so it fills whatever's left after the other children,
   reaching exactly as far down as Payment's own bottom edge instead. */
/* padding-right — scrollbar-gutter:stable reserves just enough room for
   the scrollbar itself, so with no gap of its own it renders flush
   against the row content on one side and the card's edge on the other,
   reads as cramped/touching. This pushes it inward, off both. */
.order-lines { display: grid; gap: var(--sp-4); max-height: 26rem; overflow-y: auto; padding-bottom: var(--sp-4); padding-right: var(--sp-3); border-bottom: 1px solid var(--border-faint); scrollbar-gutter: stable; }
.order-line { display: grid; grid-template-columns: 48px 1fr auto; gap: var(--sp-3); align-items: center; font-size: var(--step--2); }
/* 1:1, not 4:5 — matches .product-card__media/.search-hit__media
   sitewide; most catalogue photos are shot square, so a taller 4:5 crop
   was cutting off both sides instead of just showing the whole photo. */
.order-line img { width: 48px; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--r-xs); background: var(--media-bg); }
.order-line__qty { color: var(--text-tertiary); }
/* Checkout's own summary only (page.account.js's read-only order history/
   tracking reuses plain .order-line above, unedited, on purpose — those
   are past orders, nothing there is meant to be changeable). Two rows
   instead of one — name+price on top, qty stepper + remove below. */
/* Bigger than the base .order-line: this is the checkout's own editable
   summary, the one place the customer actively works with these rows
   (change qty, remove), so image/name/price/controls all get sized up
   from the account/payment pages' plain read-only .order-line. */
.order-line--editable { grid-template-columns: 72px 1fr; gap: var(--sp-4); }
.order-line--editable img { width: 72px; aspect-ratio: 1 / 1; }
.order-line--editable .order-line__body { display: grid; gap: var(--sp-2); align-content: start; }
.order-line--editable .order-line__top { display: flex; justify-content: space-between; gap: var(--sp-2); }
.order-line--editable .order-line__name { font-size: var(--step-0); font-weight: 600; }
.order-line--editable .order-line__price { font-size: var(--step-0); font-weight: 700; }
/* Thin rule between rows (not above the first, not doubled with
   .order-lines's own border-bottom below the last) so a long list reads
   as separate products instead of one continuous block. No padding-top
   alongside it — .order-lines's own grid gap already provides the
   spacing; adding more here would just make row 1→2 look further apart
   than every other pair. */
.order-line--editable + .order-line--editable { border-top: 1px solid var(--border-faint); }
.order-line__name { font-weight: 500; }
.order-line__variant { color: var(--text-tertiary); font-size: var(--step--2); }
.order-line__price { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* qty stepper pulled out of flow and centred in the row's own empty middle
   space; the remove button is the only element left in flex flow, so
   margin-left:auto alone pins it to the far right. top:50% + translateY
   (not just translateX) — without it the stepper had no vertical anchor
   at all and sat at its pre-absolute "static" position, which read as
   slightly crooked against the remove button's true center. Nudged a few
   px above dead-center per request. */
.order-line__controls { display: flex; align-items: center; position: relative; min-height: 44px; }
.order-line__controls .qty { position: absolute; left: 50%; top: calc(50% - 3px); transform: translate(-50%, -50%); }
.order-line__remove { display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--r-sm); color: var(--text-tertiary); margin-left: auto; }
/* Bigger + darker than the base .order-line's remove button, same idea
   as .order-add-close — a real bordered target, not a faint tertiary
   icon, since this is the main way to drop a line from the order. */
.order-line--editable .order-line__remove { width: 40px; height: 40px; color: var(--text-primary); border: 1px solid var(--border-strong); }
@media (hover: hover) { .order-line__remove:hover { color: var(--danger); background: var(--surface-sunken); border-color: var(--danger); } }

/* --- Add another product without leaving checkout -------------------- */
/* Full-width bordered button, not a plain text link — the light line
   above it is .order-lines's own border-bottom (right above this in
   source order), so the two together read as "product list, then a
   clearly separate add-product action". */
.order-add-toggle {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%;
  font-size: var(--step--1); font-weight: 700; color: var(--text-primary);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
@media (hover: hover) { .order-add-toggle:hover { background: var(--surface-sunken); border-color: var(--text-primary); } }
/* Search row + list now render INSIDE #co-lines (the same bounded,
   scrollable box the cart lines normally fill) instead of a separate
   block below the toggle button — opening "Add product" must never grow
   the card, only swap what's shown in that fixed-size area. The search
   row stays sticky to the top of that one scroll area while the list
   scrolls under it; .order-add-list itself has no scroll of its own
   (would be a confusing nested scrollbar inside #co-lines's). */
.order-add-search {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; gap: var(--sp-2);
  background: var(--surface);
  padding-bottom: var(--sp-3);
}
.order-add-search .field__input { flex: 1; }
/* Bigger + darker than a typical inline icon button, per explicit ask —
   this is the main way to back out of "Add product" mode. */
.order-add-close {
  flex-shrink: 0;
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  color: var(--text-primary);
}
@media (hover: hover) { .order-add-close:hover { background: var(--surface-sunken); border-color: var(--text-primary); } }
.order-add-list { display: grid; gap: var(--sp-3); }
/* Image/name/price were all a size down from everywhere else this same
   photo+name+price triplet shows up (product cards, search results) —
   bumped to match, and name+price now stack in their own body column
   instead of squeezing into the row alongside each other, so a
   discounted price (was+now, wider) has room to wrap without crowding
   the name. */
.order-add-row { display: grid; grid-template-columns: 52px 1fr auto; gap: var(--sp-3); align-items: center; }
.order-add-row img { width: 52px; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--r-xs); background: var(--media-bg); }
.order-add-row__body { display: grid; gap: 2px; min-width: 0; }
.order-add-row__name { font-size: var(--step--1); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.order-add-row__body .price__now { font-size: var(--step--1); }
.order-add-row__body .price__was { font-size: var(--step--2); }
.coupon-row { display: flex; gap: var(--sp-2); padding-top: var(--sp-4); border-top: 1px solid var(--border-faint); }
.coupon-row .field__input { flex: 1; }
.coupon-row--applied { justify-content: space-between; align-items: center; font-size: var(--step--1); font-weight: 600; }
.coupon-row--applied svg { vertical-align: -2px; }
.order-totals { display: grid; gap: var(--sp-2); padding-top: var(--sp-4); border-top: 1px solid var(--border-faint); }
.order-totals__row { display: flex; justify-content: space-between; font-size: var(--step--1); color: var(--text-secondary); }
.order-totals__row--grand { color: var(--text-primary); font-weight: 700; font-size: var(--step-0); padding-top: var(--sp-2); border-top: 1px solid var(--border); }

/* Full address — grows taller as the customer types instead of scrolling
   a fixed 2-line box. resize:none since the height is already automatic. */
textarea.co-address { resize: none; overflow: hidden; min-height: 4.6em; line-height: 1.5; }

/* --- District / Upazila: type-to-filter, scrollable list, same shape as
   the admin panel's own searchable selects. ------------------------- */
.loc-select { position: relative; }
.loc-select__pop {
  position: absolute; z-index: 20; top: calc(100% + 4px); left: 0; right: 0;
  max-height: 260px; overflow-y: auto;
  background: var(--bg-primary); border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
.loc-select__opt { display: block; width: 100%; text-align: left; padding: 10px 14px; font-size: var(--step--1); }
@media (hover: hover) { .loc-select__opt:hover { background: var(--surface-sunken); } }
.loc-select__empty { padding: 14px; font-size: var(--step--1); color: var(--text-tertiary); }

/* --- Payment method: three big action cards, not radios — each one
   navigates straight to its own payment page rather than just marking a
   choice, so the visual language (icon, chevron) reads as "go", not "pick". */
.payment-card {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--border-strong); border-radius: var(--r-lg);
  text-align: left; width: 100%;
  background: var(--surface);
  box-shadow: var(--shadow-1);
  transition: border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
@media (hover: hover) { .payment-card:hover { border-color: var(--text-primary); background: var(--surface-sunken); box-shadow: var(--shadow-2); transform: translateY(-1px); } }
.payment-card:active { transform: translateY(0); box-shadow: var(--shadow-1); }
.payment-card__icon {
  display: grid; place-items: center; flex-shrink: 0;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--surface-sunken); color: var(--text-primary);
  box-shadow: 0 0 0 1px var(--border-faint) inset;
}
/* one calm accent per way of paying — enough to tell them apart at a glance, without any one of the three outshining the rest */
.payment-card__icon--full { background: linear-gradient(155deg, color-mix(in srgb, var(--pay-full) 22%, transparent), color-mix(in srgb, var(--pay-full) 10%, transparent)); color: var(--pay-full); box-shadow: 0 0 0 1px color-mix(in srgb, var(--pay-full) 24%, transparent) inset; }
.payment-card__icon--delivery { background: linear-gradient(155deg, color-mix(in srgb, var(--pay-delivery) 22%, transparent), color-mix(in srgb, var(--pay-delivery) 10%, transparent)); color: var(--pay-delivery); box-shadow: 0 0 0 1px color-mix(in srgb, var(--pay-delivery) 24%, transparent) inset; }
.payment-card__icon--cod { background: var(--surface-sunken); color: var(--text-secondary); }
.payment-card__body { flex: 1; display: grid; gap: 2px; }
.payment-card__title { font-weight: 700; font-size: var(--step-0); }
.payment-card__note { font-size: var(--step--2); color: var(--text-tertiary); }
.payment-card__chevron { color: var(--text-tertiary); flex-shrink: 0; }

.cod-terms { display: grid; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5); border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); list-style: none; }
.cod-terms li { position: relative; padding-left: 1.4em; font-size: var(--step--1); color: var(--text-secondary); line-height: 1.5; }
.cod-terms li::before { content: "•"; position: absolute; left: 0.3em; color: var(--text-primary); }

/* --- Simple content pages / not found ------------------------- */
.page-hero { padding-block: var(--sp-8) var(--sp-6); }
.page-hero__title { font-size: var(--step-5); font-weight: 800; letter-spacing: -0.03em; }
.page-hero__lead { color: var(--text-secondary); font-size: var(--step-1); margin-top: var(--sp-3); max-width: 52ch; }

/* --- Categories page ------------------------------------------- */
.categories-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--sp-4);
  padding-bottom: var(--sp-9);
}
.cat-tile {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--media-bg);
}
.cat-tile__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-4) var(--ease-out); }
@media (hover: hover) { .cat-tile:hover .cat-tile__img { transform: scale(1.05); } }
.cat-tile__veil {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgba(0, 0, 0, 0.72) 100%);
}
.cat-tile__count {
  position: absolute;
  top: var(--sp-3); right: var(--sp-3);
  padding: 4px 10px;
  font-size: var(--step--2);
  font-weight: 600;
  color: #fff;
  background: rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(6px);
  border-radius: var(--r-pill);
}
.cat-tile__body {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: var(--sp-4);
  display: grid;
  gap: 4px;
  color: #fff;
}
.cat-tile__name { font-size: var(--step-1); font-weight: 800; letter-spacing: -0.01em; }
.cat-tile__blurb { font-size: var(--step--1); color: rgba(255, 255, 255, 0.8); }
.cat-tile__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: var(--step--1);
  font-weight: 600;
  transition: gap var(--dur-2) var(--ease-out);
}
@media (hover: hover) { .cat-tile:hover .cat-tile__cta { gap: 10px; } }

/* --- Info page (About / FAQ / Shipping / Returns / Privacy / Terms) --- */
.info-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-7);
}
.info-tabs__tab {
  padding: 0.55em 1em;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text-secondary);
  border: 1px solid var(--border-faint);
  border-radius: var(--r-pill);
  transition: color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.info-tabs__tab.is-active { color: var(--bg-primary); background: var(--text-primary); border-color: var(--text-primary); }
@media (hover: hover) { .info-tabs__tab:not(.is-active):hover { border-color: var(--text-primary); color: var(--text-primary); } }

.faq-list { display: grid; gap: var(--sp-3); }
.faq-item {
  border: 1px solid var(--border-faint);
  border-radius: var(--r-md);
  padding: var(--sp-4);
}
.faq-item summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  font-weight: 600;
  font-size: var(--step-0);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  flex-shrink: 0;
  font-size: 1.3em;
  line-height: 1;
  color: var(--text-tertiary);
  transition: transform var(--dur-2) var(--ease-out);
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { color: var(--text-secondary); margin-top: var(--sp-3); line-height: 1.6; }

/* --- My account (profile / orders / tracking) ------------------------- */
.account-tabs {
  display: flex;
  gap: var(--sp-2);
  border-bottom: 1px solid var(--border-faint);
  margin-bottom: var(--sp-6);
  overflow-x: auto;
  scrollbar-width: none;
}
.account-tabs::-webkit-scrollbar { display: none; }
.account-tabs__tab {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: var(--sp-3) var(--sp-2);
  font-size: var(--step-0);
  font-weight: 600;
  color: var(--text-tertiary);
  white-space: nowrap;
  transition: color var(--dur-2) var(--ease-out);
}
.account-tabs__tab svg { width: 16px; height: 16px; }
.account-tabs__tab.is-active { color: var(--text-primary); }
.account-tabs__tab.is-active::after {
  content: "";
  position: absolute;
  left: var(--sp-2); right: var(--sp-2); bottom: -1px;
  height: 2px;
  background: var(--text-primary);
}
.account-panel { max-width: 60ch; padding-bottom: var(--sp-9); }
.account-orders, .account-panel:has(.account-orders) { max-width: 72ch; }

.account-profile { display: flex; gap: var(--sp-4); align-items: flex-start; flex-wrap: wrap; }
.account-profile__avatar {
  display: grid; place-items: center;
  width: 56px; height: 56px; flex-shrink: 0;
  border-radius: var(--r-pill);
  background: hsl(var(--h) 60% 50% / 0.16); color: hsl(var(--h) 40% 35%);
  font-weight: 800; font-size: var(--step-1); letter-spacing: 0.02em;
}
:root[data-theme="dark"] .account-profile__avatar { color: hsl(var(--h) 70% 75%); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .account-profile__avatar { color: hsl(var(--h) 70% 75%); } }
.account-profile__body { flex: 1; min-width: 12rem; display: grid; gap: 2px; }
.account-profile__body h2 { font-size: var(--step-2); font-weight: 800; letter-spacing: -0.02em; }
.account-profile__body p { color: var(--text-secondary); font-size: var(--step--1); }
.account-profile__addr { color: var(--text-secondary); font-size: var(--step--1); }
.account-profile__uid b { color: var(--text-primary); letter-spacing: 0.04em; }
.account-profile__since { color: var(--text-tertiary) !important; margin-top: 4px; }
.account-profile__stats { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: 6px; }
.account-profile__stats .account-status { cursor: pointer; font: inherit; }
.account-profile__actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.account-profile__foot { margin-top: var(--sp-4); }
.account-profile-form { display: grid; gap: var(--sp-4); max-width: 32rem; }
.account-profile-form__actions { display: flex; gap: var(--sp-3); }

.account-orders { display: grid; gap: var(--sp-5); }
.account-order { border: 1px solid var(--border-faint); border-radius: var(--r-md); padding: var(--sp-4); display: grid; gap: var(--sp-4); }
.account-order__head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--sp-3); }
.account-order__head strong { font-size: var(--step-0); }
.account-order__date { display: block; color: var(--text-tertiary); font-size: var(--step--2); margin-top: 2px; }
.account-order__foot { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3); flex-wrap: wrap; padding-top: var(--sp-3); border-top: 1px solid var(--border-faint); font-size: var(--step--1); color: var(--text-secondary); }

/* --- Order status colours (My account → Orders + Tracking) -------------------------------------------------------
   Every status has its OWN colour, the same palette the TX Pet panel uses, so an order looks the same everywhere:
   placed / confirmed blue · processing violet · packed teal · ready cyan · shipped amber · out for delivery orange ·
   delivered green · cancelled red · returned rose · refunded fuchsia · failed slate.  --st is set per status; the pill,
   the timeline dots, the connecting lines and the progress bar all read it. (Dark values are re-declared under BOTH
   dark selectors — the media query must be scoped to :not([data-theme="light"]).) */
.account-panel {
  --st-blue: #2563eb; --st-violet: #7c3aed; --st-teal: #0f766e; --st-cyan: #0e7490; --st-amber: #b45309; --st-orange: #c2410c;
  --st-green: #15803d; --st-red: #dc2626; --st-rose: #be123c; --st-fuchsia: #a21caf; --st-slate: #64748b; --st-indigo: #4338ca;
}
:root[data-theme="dark"] .account-panel {
  --st-blue: #60a5fa; --st-violet: #a78bfa; --st-teal: #2dd4bf; --st-cyan: #22d3ee; --st-amber: #fbbf24; --st-orange: #fb923c;
  --st-green: #4ade80; --st-red: #f87171; --st-rose: #fb7185; --st-fuchsia: #e879f9; --st-slate: #94a3b8; --st-indigo: #818cf8;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .account-panel {
    --st-blue: #60a5fa; --st-violet: #a78bfa; --st-teal: #2dd4bf; --st-cyan: #22d3ee; --st-amber: #fbbf24; --st-orange: #fb923c;
    --st-green: #4ade80; --st-red: #f87171; --st-rose: #fb7185; --st-fuchsia: #e879f9; --st-slate: #94a3b8; --st-indigo: #818cf8;
  }
}
.st--pending, .st--placed, .st--confirmed { --st: var(--st-blue); }
.st--processing { --st: var(--st-violet); }
.st--packed { --st: var(--st-teal); }
.st--ready_to_ship { --st: var(--st-cyan); }
.st--shipped { --st: var(--st-amber); }
.st--out_for_delivery { --st: var(--st-orange); }
.st--delivered { --st: var(--st-green); }
.st--cancelled { --st: var(--st-red); }
.st--returned { --st: var(--st-rose); }
.st--refunded { --st: var(--st-fuchsia); }
.st--failed { --st: var(--st-slate); }
.st--exchange { --st: var(--st-indigo); }
/* Customer Rating / Reliability Score band (matches the admin panel's own >=80 good / >=50 warn / else bad) */
.st--rating-good { --st: var(--st-green); }
.st--rating-warn { --st: var(--st-amber); }
.st--rating-bad { --st: var(--st-red); }

/* the fallback colour sits in :where() (no specificity) so a status class such as .st--processing always wins over it */
:where(.account-status) { --st: var(--text-secondary); }
.account-status {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 11px;
  border-radius: var(--r-pill);
  font-size: var(--step--2); font-weight: 700;
  color: var(--st);
  background: color-mix(in srgb, var(--st) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--st) 40%, transparent);
  white-space: nowrap;
}
.account-status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.account-status.is-done { background: color-mix(in srgb, var(--st) 16%, transparent); border-color: var(--st); }
.account-status.is-problem { border-style: dashed; border-color: var(--st); }
.account-status.is-pay { --st: var(--st-amber); }
.account-status.is-pay.is-good { --st: var(--st-green); }

/* Rating History modal list (Customer Rating / Reliability Score, opened from the profile's rating pill) */
.rating-hist__item { display: flex; gap: var(--sp-3); padding-block: var(--sp-3); border-bottom: 1px solid var(--border-faint); text-align: left; }
.rating-hist__item:last-child { border-bottom: none; }
.rating-hist__item p { color: var(--text-tertiary); font-size: var(--step--2); margin-top: 2px; }
.review-form__stars { display: flex; gap: 4px; }
.review-form__star { color: var(--text-tertiary); padding: 2px; transition: color var(--dur-1) var(--ease-out); }
.review-form__star.is-active { color: var(--text-primary); }
.review-form__star.is-active svg { fill: currentColor; }
@media (hover: hover) { .review-form__star:hover { color: var(--text-primary); } }

.account-order-switch { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--step--1); color: var(--text-secondary); }
.account-tracking__head { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin-bottom: var(--sp-5); }
.account-tracking__head h2 { font-size: var(--step-1); font-weight: 700; }
.account-tracking .order-lines, .account-tracking .order-totals { margin-bottom: var(--sp-5); }
/* the bill card (order-bill.css) sits right under the products; the delivery / payment / courier details follow it */
.account-tracking .order-lines { padding-bottom: 0; border-bottom: 0; }
.account-tracking .ob { margin-bottom: var(--sp-5); }
.account-tracking .account-delivery { padding-top: var(--sp-4); }

/* --- Tracking: a progress bar + a timeline, each stage in its own colour --------------------------------------- */
.account-progress { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 6px; margin-bottom: var(--sp-5); }
.account-progress__seg { height: 6px; border-radius: 99px; background: var(--border); --st: var(--text-tertiary); position: relative; overflow: hidden; }
.account-progress__seg.is-done, .account-progress__seg.is-current { background: var(--st); }
.account-progress__seg.is-current::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, color-mix(in srgb, #fff 55%, transparent), transparent); transform: translateX(-100%); animation: acc-sheen 1.8s var(--ease-in-out) infinite; }
@keyframes acc-sheen { to { transform: translateX(100%); } }

.account-now { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin-bottom: var(--sp-5); }
.account-now__note { color: var(--text-secondary); font-size: var(--step--1); }

:where(.account-problem) { --st: var(--danger); }
.account-problem {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: var(--sp-4); margin-bottom: var(--sp-5);
  border: 1px solid color-mix(in srgb, var(--st) 45%, transparent); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--st) 9%, transparent);
  font-size: var(--step--1); color: var(--text-secondary);
}
.account-problem strong { display: block; color: var(--st); font-size: var(--step-0); margin-bottom: 2px; }
.account-problem svg { color: var(--st); flex-shrink: 0; margin-top: 2px; }

/* "Complete payment" — a claim from checkout was rejected, or never finished; --pay-tax (the same amber as the
   VAT-surcharge badge) reads as "needs your attention" without the alarm of the account-problem red above */
.account-payretry {
  display: grid; gap: var(--sp-3);
  padding: var(--sp-4); margin-bottom: var(--sp-5);
  border: 1px solid color-mix(in srgb, var(--pay-tax) 45%, transparent); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--pay-tax) 9%, transparent);
}
.account-payretry__head { display: flex; gap: var(--sp-3); align-items: flex-start; font-size: var(--step--1); color: var(--text-secondary); }
.account-payretry__head strong { display: block; color: var(--pay-tax); font-size: var(--step-0); margin-bottom: 2px; }
.account-payretry__head svg { color: var(--pay-tax); flex-shrink: 0; margin-top: 2px; }
.account-payretry__amt { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm); background: var(--surface); font-size: var(--step--1); color: var(--text-secondary); }
.account-payretry__amt b { font-size: var(--step-1); color: var(--text-primary); font-variant-numeric: tabular-nums; }
.account-payretry__form { display: grid; gap: var(--sp-3); padding-top: var(--sp-2); border-top: 1px dashed color-mix(in srgb, var(--pay-tax) 35%, transparent); }
.account-payretry__target { margin: 0; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm); background: var(--surface); font-size: var(--step--1); color: var(--text-secondary); }
.account-payretry__target b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.account-payretry__acts { display: flex; justify-content: flex-end; gap: var(--sp-3); }
/* the delivery charge is verified and settled — same layout, calm green instead of amber, never a button */
.account-payretry.is-settled { border-color: color-mix(in srgb, var(--st-green) 45%, transparent); background: color-mix(in srgb, var(--st-green) 9%, transparent); }
.account-payretry.is-settled .account-payretry__head strong, .account-payretry.is-settled .account-payretry__head svg { color: var(--st-green); }

.account-timeline { display: grid; gap: 0; margin-bottom: var(--sp-6); }
.account-timeline__step { --st: var(--text-tertiary); display: flex; gap: var(--sp-3); padding-bottom: var(--sp-5); position: relative; }
.account-timeline__step:not(:last-child)::before {
  content: ""; position: absolute; left: 11px; top: 26px; bottom: 2px; width: 2px; border-radius: 2px;
  background: var(--border);
}
.account-timeline__step.is-done:not(:last-child)::before { background: linear-gradient(to bottom, var(--st), var(--next, var(--st))); }
.account-timeline__dot {
  display: grid; place-items: center;
  width: 24px; height: 24px; flex-shrink: 0;
  border-radius: var(--r-pill);
  border: 2px solid var(--border-strong);
  background: var(--bg-primary);
  color: #fff;
  z-index: 1;
}
.account-timeline__step.is-done .account-timeline__dot { background: var(--st); border-color: var(--st); }
.account-timeline__step.is-current .account-timeline__dot { border-color: var(--st); background: var(--bg-primary); color: var(--st); animation: acc-pulse 1.9s ease-out infinite; }
.account-timeline__step.is-current .account-timeline__dot::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--st); }
@keyframes acc-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--st) 45%, transparent); } 70% { box-shadow: 0 0 0 9px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
@media (prefers-reduced-motion: reduce) { .account-timeline__step.is-current .account-timeline__dot, .account-progress__seg.is-current::after { animation: none; } }
.account-timeline__step.is-upcoming { opacity: 0.55; }
.account-timeline__step.is-done strong, .account-timeline__step.is-current strong { color: var(--st); }
.account-timeline__step strong { font-size: var(--step--1); }
.account-timeline__step p { color: var(--text-tertiary); font-size: var(--step--2); margin-top: 2px; }
.account-timeline__when { display: block; color: var(--text-secondary); font-size: var(--step--2); margin-top: 3px; font-variant-numeric: tabular-nums; }
.account-timeline__msg { display: inline-block; margin-top: 6px; padding: 5px 10px; border-radius: var(--r-sm); background: var(--surface-sunken); color: var(--text-secondary); font-size: var(--step--2); }
/* an admin note collapsed to ONE line with a "More" toggle — same clamp + toggle idea as .pdp__desc / .pdp__desc-more */
.account-note { display: block; }
.account-note-sent { display: block; margin-top: 8px; }
.account-note__text { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; max-width: 52ch; overflow-wrap: anywhere; white-space: pre-line; }
.account-note__text.is-expanded { display: inline-block; -webkit-line-clamp: unset; overflow: visible; }
.account-note__more { display: block; margin-top: 4px; font-size: var(--step--2); font-weight: 700; color: var(--text-tertiary); text-decoration: underline; text-underline-offset: 2px; }
@media (hover: hover) { .account-note__more:hover { color: var(--text-primary); } }
.acc-stage--placed { --st: var(--st-blue); } .acc-stage--processing { --st: var(--st-violet); } .acc-stage--shipped { --st: var(--st-amber); } .acc-stage--delivered { --st: var(--st-green); }

/* order lines (My orders + Tracking): the photo, the name, the chosen options, the quantity */
.order-line img { background: var(--media-bg); }
.order-line__var { display: block; color: var(--text-tertiary); font-size: var(--step--2); }
.order-pay { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }

/* ==========================================================================
   Checkout payment step + the Payment page
   The page chrome stays black and white; the colour comes from the payment methods themselves — each one's real logo
   (assets/css/paylogo.css) on a white tile, and its brand colour (--brand) for the hover ring, the selected ring and the tick.
   ========================================================================== */

/* the three plan cards on checkout now show what they charge right now */
.pay-cards { display: grid; gap: var(--sp-3); }
.payment-card__amt { display: grid; justify-items: end; gap: 1px; flex-shrink: 0; text-align: right; }
.payment-card__amt s { font-size: var(--step--2); font-weight: 600; color: var(--text-tertiary); text-decoration-thickness: 1.5px; }
.payment-card__amt small { font-size: var(--step--2); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-tertiary); }
.payment-card__amt b { font-size: var(--step-1); font-weight: 800; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.payment-card.is-disabled { opacity: 0.55; cursor: not-allowed; background: var(--surface-sunken); border-style: dashed; box-shadow: none; }
@media (hover: hover) { .payment-card.is-disabled:hover { border-color: var(--border-strong); background: var(--surface-sunken); box-shadow: none; transform: none; } }
.payment-card.is-disabled .payment-card__chevron { visibility: hidden; }
/* the shop's recommended way of paying (Admin → Payment methods → Checkout offers) stands out — a solid ring, never a colour block */
.payment-card { position: relative; }
/* the recommended way of paying is drawn deliberately bigger — not scaled, its own box gets more room — so it
   reads as the shop's pick before anyone even reads the words */
.payment-card.is-recommended {
  border: 1.5px solid var(--text-primary);
  padding: calc(var(--sp-4) + 14px) calc(var(--sp-5) + 4px) calc(var(--sp-4) + 4px);
  box-shadow: var(--shadow-2);
  background: var(--surface-raised);
}
@media (hover: hover) { .payment-card.is-recommended:hover { box-shadow: var(--shadow-pop); } }
.payment-card.is-recommended .payment-card__icon { width: 52px; height: 52px; }
.payment-card.is-recommended .payment-card__title { font-size: var(--step-1); }
.payment-card.is-recommended .payment-card__amt b { font-size: var(--step-2); }
.payment-card__rec { position: absolute; top: 0; left: var(--sp-5); transform: translateY(-50%); padding: 2px 10px; border-radius: var(--r-pill); background: var(--text-primary); color: var(--bg-primary); font-size: 10.5px; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; }
.payment-card__title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.payment-card__badge { display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px; border-radius: var(--r-pill); background: color-mix(in srgb, var(--pay-delivery) 16%, transparent); color: var(--pay-delivery); font-size: 10.5px; font-weight: 800; }
.payment-card__badge svg { flex-shrink: 0; }
/* A VAT/tax surcharge on the delivery charge (a negative "discount" percent) reads as a warning, not an
   offer — customers should see "this costs more" without reading the wording. */
.payment-card__badge--tax { background: color-mix(in srgb, var(--pay-tax) 16%, transparent); color: var(--pay-tax); }

.pay-accept { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pay-accept__t { font-size: var(--step--2); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-tertiary); margin-right: 4px; }
@media (max-width: 520px) { .payment-card { gap: var(--sp-3); padding-inline: var(--sp-4); } .payment-card__chevron { display: none; } .payment-card__icon { width: 38px; height: 38px; } .payment-card__rec { left: var(--sp-4); } .payment-card.is-recommended { padding-inline: calc(var(--sp-4) + 4px); } .payment-card.is-recommended .payment-card__icon { width: 44px; height: 44px; } }
.pay-alert, .pay-error { padding: var(--sp-3) var(--sp-4); border: 1px solid var(--danger); background: var(--danger-bg); color: var(--danger); border-radius: var(--r-md); font-size: var(--step--1); line-height: 1.5; }
.pay-error[hidden] { display: none; }
.pay-error p { margin: 0; }
.pay-error__acts { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-3); }
.pay-retry { justify-self: start; }

/* --- Payment page ------------------------------------------------------------------------------------------- */
.pay-page .checkout__form { align-content: start; }
@media (min-width: 940px) { .pay-page { grid-template-columns: 1.05fr 0.95fr; align-items: start; } }

/* the amount to pay, front and centre: an inverted (ink) panel with a fine diagonal grain */
.pay-hero {
  position: relative; overflow: hidden;
  display: grid; gap: var(--sp-3);
  padding: var(--sp-6) var(--sp-6) var(--sp-5);
  border-radius: var(--r-lg);
  background: var(--text-primary); color: var(--bg-primary);
}
.pay-hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--bg-primary) 7%, transparent) 0 1px, transparent 1px 13px);
}
.pay-hero > * { position: relative; }
.pay-hero__plan { justify-self: start; padding: 4px 11px; border-radius: var(--r-pill); border: 1px solid color-mix(in srgb, var(--bg-primary) 35%, transparent); font-size: var(--step--2); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; }
.pay-hero__amt { display: grid; gap: 2px; }
.pay-hero__amt small { font-size: var(--step--1); font-weight: 600; opacity: 0.7; }
.pay-hero__amt b { font-size: var(--step-6); line-height: 1; font-weight: 800; letter-spacing: -0.035em; font-variant-numeric: tabular-nums; }
.pay-hero__note { font-size: var(--step--1); opacity: 0.75; max-width: 46ch; line-height: 1.5; }
/* cash on delivery: its mark sits in the corner of the ink panel */
.pay-hero > .pay-hero__logo { position: absolute; top: var(--sp-5); right: var(--sp-6); filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.35)); }

.pay-group { display: grid; gap: var(--sp-2); }
.pay-group__t { font-size: var(--step--2); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-tertiary); }
/* the way to pay is picked by its logo: a card per method, the logo on its white tile, the name under it */
.pay-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 8.6rem), 1fr)); gap: var(--sp-3); }
.pay-tile {
  --brand: var(--chip, #334155);
  position: relative; display: grid; justify-items: center; align-content: center; gap: var(--sp-2);
  min-height: 112px; padding: var(--sp-4) var(--sp-3) var(--sp-3);
  border: 1.5px solid var(--border-strong); border-radius: var(--r-md); background: var(--surface);
  text-align: center; cursor: pointer;
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.pay-tile input { position: absolute; inset: 0; opacity: 0; cursor: pointer; margin: 0; }
.pay-tile .pay-logo { --pl-h: 54px; width: min(100%, 9.2rem); }
.pay-tile .pay-logo--emblem { width: var(--pl-h); }
@media (hover: hover) { .pay-tile:hover { border-color: color-mix(in srgb, var(--brand) 60%, var(--border-strong)); transform: translateY(-2px); box-shadow: 0 10px 22px -12px color-mix(in srgb, var(--brand) 60%, transparent); } }
.pay-tile:has(input:checked) { border-color: var(--brand); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent); transform: none; }
.pay-tile:has(input:focus-visible) { outline: 2px solid var(--text-primary); outline-offset: 2px; }
.pay-tile__name { font-weight: 700; font-size: var(--step--1); line-height: 1.2; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pay-tile__check { position: absolute; top: 8px; right: 8px; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: var(--brand); color: #fff; opacity: 0; transform: scale(0.5); transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }
.pay-tile:has(input:checked) .pay-tile__check { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .pay-tile, .pay-tile__check { transition: none; } .pay-tile:hover { transform: none; } }

.pay-detail { padding: var(--sp-5); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); gap: var(--sp-4); }
.pay-detail__head { display: flex; align-items: center; gap: var(--sp-3); }
.order-pay-line { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--sp-2); flex-wrap: wrap; text-align: right; }
.pay-detail__head h3 { font-size: var(--step-0); font-weight: 700; }
.pay-pick { color: var(--text-tertiary); font-size: var(--step--1); }
.pay-note { padding: var(--sp-3) var(--sp-4); border-radius: var(--r-md); background: var(--surface-sunken); color: var(--text-secondary); font-size: var(--step--1); line-height: 1.5; }
.pay-steps { list-style: none; counter-reset: paystep; display: grid; gap: var(--sp-3); }
.pay-steps li { counter-increment: paystep; position: relative; padding-left: 2.2rem; font-size: var(--step--1); color: var(--text-secondary); line-height: 1.5; }
.pay-steps li::before { content: counter(paystep); position: absolute; left: 0; top: -1px; display: grid; place-items: center; width: 1.55rem; height: 1.55rem; border-radius: 50%; background: var(--text-primary); color: var(--bg-primary); font-size: 11px; font-weight: 800; }

.pay-target { display: grid; border: 1.5px dashed var(--border-strong); border-radius: var(--r-md); }
.pay-target__row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); }
.pay-target__row + .pay-target__row { border-top: 1px dashed var(--border-strong); }
.pay-target small { display: block; font-size: var(--step--2); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-tertiary); }
.pay-target b { font-size: var(--step-1); font-weight: 800; font-variant-numeric: tabular-nums; }
.pay-target__no { font-size: var(--step-2) !important; letter-spacing: 0.04em; }
.pay-target__acct { white-space: pre-wrap; font-size: var(--step-0) !important; line-height: 1.45; display: block; }
.pay-copy { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border: 1px solid var(--border-strong); border-radius: var(--r-pill); font-size: var(--step--2); font-weight: 700; flex-shrink: 0; transition: background var(--dur-1), color var(--dur-1); }
@media (hover: hover) { .pay-copy:hover { background: var(--text-primary); color: var(--bg-primary); } }
.pay-copy.is-done { background: var(--text-primary); color: var(--bg-primary); }
.pay-link { justify-content: center; }
/* the optional payment-claim screenshot — a single photo, uploaded immediately on pick */
.pay-shot { display: flex; align-items: center; gap: var(--sp-3); }
.pay-shot__add { display: inline-flex; align-items: center; gap: 8px; padding: var(--sp-3) var(--sp-4); border: 1.5px dashed var(--border-strong); border-radius: var(--r-md); color: var(--text-secondary); font-size: var(--step--1); font-weight: 700; transition: border-color var(--dur-1), color var(--dur-1); }
@media (hover: hover) { .pay-shot__add:hover { border-color: var(--text-primary); color: var(--text-primary); } }
.pay-shot__thumb { width: 56px; height: 56px; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--border-strong); flex-shrink: 0; }
.pay-shot__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pay-shot__rm { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--border-strong); color: var(--text-secondary); flex-shrink: 0; }
@media (hover: hover) { .pay-shot__rm:hover { border-color: var(--danger); color: var(--danger); } }
.pay-shot__busy { display: inline-flex; align-items: center; gap: 8px; font-size: var(--step--1); color: var(--text-tertiary); }
.pay-shot__spin { width: 16px; height: 16px; border: 2px solid var(--border-strong); border-top-color: var(--text-primary); border-radius: 50%; animation: tx-spin 0.7s linear infinite; }
.pay-agree { display: flex; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-4); border: 1px solid var(--border-strong); border-radius: var(--r-md); cursor: pointer; font-size: var(--step--1); font-weight: 600; }
.pay-agree input { margin-top: 3px; width: 18px; height: 18px; accent-color: var(--text-primary); flex-shrink: 0; }
.pay-confirm { min-height: 52px; font-size: var(--step-0); }
.order-totals__row--pay { color: var(--text-primary); font-weight: 800; }
.placed-next { max-width: 56ch; margin-inline: auto; }
.placed-method { display: flex; justify-content: center; margin-top: var(--sp-4); }
@media (max-width: 560px) { .pay-hero { padding: var(--sp-5); } .pay-hero > .pay-hero__logo { top: var(--sp-4); right: var(--sp-4); --pl-h: 52px; } .pay-target__no { font-size: var(--step-1) !important; } }

/* the line under the delivery choice: time, the shop's notice, or "we do not deliver here" */
.delivery-note { margin: var(--sp-3) 0 0; padding: 10px 14px; border: 1px solid var(--border-strong); border-radius: var(--r-sm); background: var(--surface-sunken); font-size: var(--step--1); color: var(--text-secondary); line-height: 1.5; }
.delivery-note[hidden] { display: none; }
.delivery-note.is-bad { border-color: color-mix(in srgb, var(--danger) 55%, transparent); background: color-mix(in srgb, var(--danger) 8%, transparent); color: var(--danger); font-weight: 600; }

/* the shop's delivery charges by place, under the shipping policy */
.info-rates__wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-sm); }
.info-rates table { width: 100%; border-collapse: collapse; font-size: var(--step--1); }
.info-rates th, .info-rates td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border-faint, var(--border)); white-space: nowrap; }
.info-rates th { background: var(--surface-sunken); font-size: var(--step--2); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); }
.info-rates tr:last-child td { border-bottom: 0; }
.info-rates { margin-top: var(--sp-8); }


/* --- product page before its script runs (backend/lib/Seo.php writes the product's name, photo, text and price into
       #pdp-root for search engines and slow connections; page.product.js replaces it with the full page at once) --- */
.pdp-ssr { display: grid; gap: var(--sp-3); padding-block: var(--sp-6); max-width: 60ch; }
.pdp-ssr h1 { font-family: var(--font-display); font-weight: 800; font-size: var(--step-3); letter-spacing: -0.02em; line-height: 1.1; }
.pdp-ssr img { width: min(420px, 100%); height: auto; aspect-ratio: 1; object-fit: contain; border-radius: var(--r-md); background: var(--bg-primary); }
.pdp-ssr p { color: var(--text-secondary); }
.pdp-ssr strong { color: var(--text-primary); font-size: var(--step-1); }