/* ==========================================================================
   Driftball - "Match Day" design system (black/gold, see section 1)
   Loaded AFTER Bootstrap, so anything here overrides Bootstrap's defaults.
   Organized as: 1) design tokens, 2) base/typography, 3) nav, 4) buttons,
   5) cards, 6) forms, 7) hero, 8) misc page bits, 9) chat assistant widget.
   ========================================================================== */

/* --- 1. Design tokens ---------------------------------------------------- */
:root {
  /* "Match Day" palette - built to sit behind the black/gold Driftball
     emblem (static/brand/) instead of the old green "Tashkent Football
     Store" identity. --color-primary is now a near-black (used for the
     nav/footer bookend, ink, and dark surfaces) and --color-accent is the
     brand gold, promoted from "used sparingly" to the site's one real
     accent color - every CTA, active state, and highlight funnels through
     it so there's a single consistent "pop" color instead of competing
     with green. */
  --color-primary: #16181c;
  --color-primary-dark: #0a0b0d;
  --color-primary-light: #eceef1;
  --color-accent: #e3a73b;        /* Driftball gold - the site's one accent color, used deliberately, not sparingly */
  --color-accent-dark: #b8841f;
  --color-accent-light: #fbf0dc;  /* pale gold wash for icon-circle backgrounds, badges, subtle highlight fills */
  --color-accent-deep: #8f640d;   /* darker gold-brown, contrast-checked (5.25:1 on white, 4.65:1 on --color-accent-light) for gold TEXT on a light background - --color-accent-dark alone is only 3.3:1 there (fails WCAG AA), so it stays reserved for hover fills/borders where dark text sits on top of it instead */
  --color-ink: #16181c;           /* near-black text - same tone as --color-primary on purpose, one dark color for the whole site */
  --color-muted: #6b7280;
  --color-bg: #f5f5f7;
  --color-surface: #ffffff;
  --color-border: #e5e7eb;
  --color-danger: #d64545;
  --color-success: #1a9c53;
  --color-warning: #b8790a;

  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 3px rgba(10, 11, 13, 0.07), 0 1px 2px rgba(10, 11, 13, 0.09);
  --shadow-md: 0 8px 24px rgba(10, 11, 13, 0.12);
  --shadow-lg: 0 20px 48px rgba(10, 11, 13, 0.22);

  /* Oswald: a tall, condensed, heavy-weight face - reads like stadium
     signage/jersey lettering rather than the old Poppins' soft rounded
     geometry, which is the single biggest lever for making the site feel
     like a sports brand instead of a generic storefront. Poppins kept as
     the first fallback (not dropped from the Google Fonts link below)
     so a slow/blocked font load still lands on a reasonably bold face
     instead of jumping straight to the system default. */
  --font-display: "Oswald", "Poppins", system-ui, sans-serif;
  --font-body: "Inter", system-ui, -apple-system, sans-serif;
}

/* --- 2. Base / typography ------------------------------------------------- */
html, body {
  height: 100%;
}

body {
  /* Tells the browser this page is only designed for a light UI (form
     controls, scrollbars, etc.) so it doesn't try to auto-darken anything
     on a device set to dark mode - avoiding mismatched, half-dark form
     fields on an otherwise light page. */
  color-scheme: light;
  background-color: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 600;
  /* Oswald is condensed by design - negative tracking (the old Poppins
     value) crams it further; a touch of positive tracking instead keeps
     it feeling bold rather than squeezed. */
  letter-spacing: 0.01em;
  text-wrap: balance;
  color: var(--color-ink);
}

a {
  /* Accent gold, not --color-primary-dark - now that primary-dark is a
     near-black, it would be visually indistinguishable from plain body
     text (--color-ink is the same near-black). Gold is the site's one
     accent color (see section 1), so it's also what makes a link
     actually read as a link. --color-accent-deep (not -dark) specifically:
     contrast-checked at 5.25:1 on white text - -dark alone is only 3.3:1
     as text and fails WCAG AA. */
  color: var(--color-accent-deep);
}

.page-content {
  flex: 1 0 auto;
  padding-top: 2rem;
  /* Extra clearance (not just 3rem) so the fixed assistant-launcher button
     (see section 9 below - it's pinned bottom:1.25rem, roughly 4.4rem
     tall including its own offset) never ends up sitting on top of real
     content at the bottom of a short page. Confirmed with a real browser:
     without this, scrolling a short page (e.g. the order confirmation
     page) to its end put the button directly over the payment
     instructions' last line of text. */
  padding-bottom: 6rem;
}

/* Flash message with an attached call-to-action (see the "cart_added"
   category in base.html / blueprints/shop/routes.py add_to_cart). Falls
   back gracefully to normal stacked layout on narrow screens. */
.flash-with-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.flash-cta {
  flex-shrink: 0;
  font-weight: 600;
  white-space: nowrap;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* --- 3. Nav ---------------------------------------------------------------- */
.site-nav {
  /* Black "bookend" - the nav and footer share this near-black so the
     light content area reads as one page framed top and bottom, with
     the gold accent doing all the popping in between. */
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(17, 19, 23, 0.94);
  backdrop-filter: saturate(160%) blur(10px);
  -webkit-backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 2px solid var(--color-accent);
}

.site-nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 0;
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.15rem;
  color: #fff;
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: var(--radius-pill);
  background: #0d0d0f;
  color: #fff;
  font-size: 1.1rem;
  overflow: hidden;
  flex-shrink: 0;
  /* Thin gold ring so the dark logo badge doesn't disappear into the
     now-equally-dark nav background. */
  box-shadow: 0 0 0 1.5px var(--color-accent);
}

.brand-mark img {
  width: 78%;
  height: 78%;
  object-fit: contain;
  display: block;
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.nav-link-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.9rem;
  border-radius: var(--radius-pill);
  text-decoration: none;
  color: rgba(255, 255, 255, 0.85);
  font-weight: 600;
  font-size: 0.92rem;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.nav-link-pill:hover {
  background: var(--color-accent);
  color: #241a00;
}

.cart-badge {
  background: var(--color-accent);
  color: #3a2a00;
  border-radius: var(--radius-pill);
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.05rem 0.45rem;
  line-height: 1.4;
}

.lang-switcher {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-pill);
  padding: 0.2rem;
  margin-left: 0.25rem;
}

.lang-pill {
  padding: 0.3rem 0.65rem;
  border-radius: var(--radius-pill);
  font-size: 0.78rem;
  font-weight: 700;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.6);
  letter-spacing: 0.02em;
}

.lang-pill.active {
  background: var(--color-accent);
  color: #241a00;
}

.lang-pill:not(.active):hover {
  color: #fff;
}

.flash-container {
  padding-top: 1rem;
}

.app-alert {
  border: none;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

/* --- 4. Buttons -------------------------------------------------------------- */
.btn {
  border-radius: var(--radius-pill);
  font-weight: 600;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.btn-primary {
  /* Primary CTA is now gold-filled, not black-filled - it's the one
     button style that should always read as "the thing to click". */
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #241a00;
}

.btn-primary:hover, .btn-primary:focus {
  background: var(--color-accent-dark);
  border-color: var(--color-accent-dark);
  color: #241a00;
}

.btn-outline-primary {
  color: var(--color-accent-deep);
  border-color: var(--color-accent);
}

.btn-outline-primary:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #241a00;
}

.btn-lg {
  padding-top: 0.7rem;
  padding-bottom: 0.7rem;
  font-size: 1.02rem;
}

.btn-dark {
  background: var(--color-ink);
  border-color: var(--color-ink);
}

/* --- 5. Cards ---------------------------------------------------------------- */
.card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
  overflow: hidden;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-accent);
}

.card-img-top {
  height: 170px;
  object-fit: contain;
  background: linear-gradient(180deg, #fbfbfc 0%, #f0f0f2 100%);
  padding: 1.25rem;
}

.card-body {
  padding: 1.1rem 1.15rem 1.25rem;
}

.grade-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--color-accent-light);
  color: var(--color-accent-deep);
}

.price-tag {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--color-ink);
}

.stock-line.in-stock { color: var(--color-success); }
.stock-line.out-of-stock { color: var(--color-danger); font-weight: 600; }

/* --- 6. Forms ------------------------------------------------------------------ */
.form-control, .form-select {
  border-radius: var(--radius-sm);
  border-color: var(--color-border);
  padding: 0.6rem 0.85rem;
}

.form-control:focus, .form-select:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 0.2rem var(--color-accent-light);
}

.form-label {
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--color-ink);
}

/* --- 6b. Payment method picker (checkout) --------------------------------------- */
/* Icon-carrying, card-style radio buttons instead of a plain native
   <select> dropdown - lets a customer see and compare all payment
   options at a glance instead of reading text labels one at a time
   inside a closed dropdown. The <input type="radio"> itself is kept
   (never display:none) so keyboard navigation, screen readers and
   autofill all keep working exactly like a normal radio group - only
   its accent color is themed, and the surrounding <label> is what
   gets the big clickable card treatment. */
.payment-option-group {
  display: grid;
  /* 230px (not 150px) because several of these labels are full sentences
     ("Pay with Click (send screenshot via Telegram)") - at 150px they wrapped
     to 4-5 lines per card, which combined with align-items:center below to
     make the radio dot and icon float in the middle of a wrapped paragraph
     instead of next to the first line. Confirmed visually with a real
     browser screenshot before and after this change. */
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0.75rem;
}

.payment-option {
  display: flex;
  /* flex-start (not center): with align-items:center, a card whose label
     wraps to several lines had its radio+icon centered against the WHOLE
     wrapped block, so they ended up floating next to the middle line of
     text instead of the first one. flex-start keeps them pinned to the
     top, in line with where the label actually starts. The 0.15rem
     top padding on the radio/icon below then nudges them down just enough
     to align with the label's first line of text rather than its very top
     edge. */
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.75rem 0.9rem;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.payment-option:hover {
  border-color: var(--color-accent);
}

.payment-option input[type="radio"] {
  /* Tints the native radio control itself to match the brand rather than
     hiding it behind a custom-drawn one - keeps native platform behavior
     (keyboard focus ring, touch target, screen-reader state) intact. */
  accent-color: var(--color-accent-dark);
  width: 1.05rem;
  height: 1.05rem;
  flex-shrink: 0;
  margin-top: 0.2rem;
}

.payment-option-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--color-accent-light);
  color: var(--color-accent-deep);
  flex-shrink: 0;
}

.payment-option-label {
  font-weight: 600;
  font-size: 0.92rem;
  padding-top: 0.15rem;
}

/* Highlights the whole card when its own radio is checked - :has() is
   Baseline widely available (all major browsers since Dec 2023), but a
   JS fallback for the small remaining sliver of older browsers is
   registered in checkout.html via @supports not selector(:has(*)) below. */
.payment-option:has(input:checked) {
  border-color: var(--color-accent-dark);
  background: var(--color-accent-light);
}

@supports not selector(:has(*)) {
  .payment-option.is-checked {
    border-color: var(--color-accent-dark);
    background: var(--color-accent-light);
  }
}

/* --- 7. Hero -------------------------------------------------------------------- */
.hero {
  position: relative;
  border-radius: var(--radius-lg);
  padding: clamp(2.25rem, 5vw, 4rem);
  margin-bottom: 2.5rem;
  overflow: hidden;
  background:
    radial-gradient(circle at 88% 12%, rgba(227, 167, 59, 0.35) 0%, rgba(227, 167, 59, 0) 55%),
    linear-gradient(135deg, #0a0b0d 0%, #16181c 55%, #1f2229 100%);
  color: #fff;
  box-shadow: var(--shadow-lg);
}

.hero::after {
  content: "";
  position: absolute;
  right: -60px;
  bottom: -80px;
  width: 260px;
  height: 260px;
  border-radius: 50%;
  border: 26px dashed rgba(255, 255, 255, 0.12);
}

.hero h1 {
  color: #fff;
  font-size: clamp(1.75rem, 3.4vw, 2.6rem);
  max-width: 34ch;
  margin-bottom: 0.9rem;
}

.hero p {
  color: rgba(255, 255, 255, 0.9);
  max-width: 52ch;
  font-size: 1.05rem;
  margin-bottom: 1.6rem;
}

/* No .hero .btn-primary override needed - the global .btn-primary (see
   section 4) is already gold-filled with dark text, which reads perfectly
   on this hero's black background without a hero-specific re-skin. */

/* --- 7b. Football-themed landing hero -------------------------------------- */
/* Pitch-stripe backdrop: faint diagonal mown-grass bands in translucent
   white, running behind the black hero gradient, plus a faint center-circle
   arc. Kept subtle (low opacity, behind hero::after's dashed circle) so the
   hero copy stays fully readable. */
.hero-pitch {
  isolation: isolate;
}

.hero-pitch-lines {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: repeating-linear-gradient(
    100deg,
    rgba(255, 255, 255, 0.05) 0,
    rgba(255, 255, 255, 0.05) 60px,
    transparent 60px,
    transparent 120px
  );
  pointer-events: none;
}

.hero-pitch-lines::after {
  content: "";
  position: absolute;
  left: 8%;
  top: 50%;
  width: 220px;
  height: 220px;
  transform: translateY(-50%);
  border: 2px solid rgba(255, 255, 255, 0.14);
  border-radius: 50%;
}

.hero-inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
}

.hero-copy {
  flex: 1 1 auto;
  min-width: 0;
}

.hero-kicker {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 0.6rem;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}

.hero-ai-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: #fff;
  font-weight: 600;
  font-size: 0.92rem;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.45);
  padding-bottom: 2px;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.hero-ai-link svg {
  color: var(--color-accent);
  flex-shrink: 0;
}

.hero-ai-link:hover {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

.hero-ball-wrap {
  flex: 0 0 auto;
  display: none;
}

.hero-ball {
  width: clamp(120px, 14vw, 190px);
  height: auto;
  filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.25));
  animation: hero-ball-spin 22s linear infinite;
}

@keyframes hero-ball-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

@media (min-width: 768px) {
  .hero-ball-wrap {
    display: block;
  }
}

/* --- 7b-ii. Optional hero background video ---------------------------------- */
/* Only present in the DOM when HERO_VIDEO_FILE is set (config.py) - see
   templates/shop/home.html. object-fit: cover crops the video to fill the
   hero exactly like a CSS background-image would, regardless of the
   source video's own aspect ratio. .hero-pitch already has
   `overflow: hidden` (section 7) so a video wider/taller than the hero
   never spills outside its rounded corners. */
.hero-video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Darkens the video so .hero-copy's white text (unchanged, still
   .hero-inner's z-index: 1) stays readable no matter what's playing
   underneath - the same gradient direction/colors as the non-video hero
   background above, so turning the video on doesn't change the hero's
   overall color mood, just adds motion to it. */
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(circle at 88% 12%, rgba(227, 167, 59, 0.25) 0%, rgba(227, 167, 59, 0) 55%),
    linear-gradient(135deg, rgba(10, 11, 13, 0.86) 0%, rgba(22, 24, 28, 0.78) 60%, rgba(31, 34, 41, 0.72) 100%);
}

/* --- 7c. Stats bar ------------------------------------------------------------ */
.stats-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
  margin-bottom: 2.5rem;
}

.stat-tile {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 0.9rem 1.1rem;
}

.stat-icon {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-pill);
  background: var(--color-accent-light);
  color: var(--color-accent-deep);
}

.stat-text {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--color-ink);
  line-height: 1.3;
}

/* --- 7c-ii. "Why shop with us" trust cards ------------------------------------- */
/* See the HTML comment above this block in templates/shop/home.html for
   why this is 4 verifiable facts about the store instead of fabricated
   review counts/customer numbers - a brand-new store with 0 real orders
   yet. Visually heavier than .stat-tile above (bigger icon, a title AND a
   sentence of body copy) on purpose, so this doesn't just look like a
   restatement of the stats bar above it. */
.trust-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  margin-bottom: 2.75rem;
}

.trust-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 1.25rem 1.35rem;
}

.trust-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  margin-bottom: 0.75rem;
  border-radius: var(--radius-pill);
  background: var(--color-accent-light);
  color: var(--color-accent-deep);
}

.trust-card-title {
  font-size: 0.98rem;
  margin-bottom: 0.35rem;
}

.trust-card-text {
  font-size: 0.86rem;
  color: var(--color-muted);
  margin-bottom: 0;
  line-height: 1.5;
}

/* --- 7d. Shop-by-grade cards --------------------------------------------------- */
.grade-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1rem;
  margin-bottom: 2.75rem;
}

.grade-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 1.1rem 1.2rem;
  text-decoration: none;
  color: inherit;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.grade-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-accent);
}

.grade-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pill);
  background: var(--color-accent-light);
  color: var(--color-accent-deep);
}

.grade-card-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--color-ink);
}

.grade-card-count {
  font-size: 0.8rem;
  color: var(--color-muted);
  font-weight: 600;
}

/* --- 7e. AI assistant CTA banner ------------------------------------------------ */
.ai-banner {
  /* Dark card (matches the hero/nav/footer bookend) rather than the old
     light green-tinted panel - makes the AI assistant CTA read as a
     distinct, deliberate feature rather than just another light-gray box
     on an already-light page. */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem;
  background: linear-gradient(135deg, var(--color-ink) 0%, #23262d 100%);
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  margin-top: 3rem;
}

.ai-banner-icon {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-pill);
  background: #fff;
  color: var(--color-accent-deep);
  box-shadow: var(--shadow-sm);
}

.ai-banner-copy {
  flex: 1 1 320px;
  min-width: 0;
}

.ai-banner-copy h3 {
  color: #fff;
  font-size: 1.15rem;
  margin-bottom: 0.3rem;
}

.ai-banner-copy p {
  color: rgba(255, 255, 255, 0.72);
  margin: 0;
  font-size: 0.94rem;
}

.ai-banner-cta {
  flex-shrink: 0;
}

/* --- 8. Misc page bits ----------------------------------------------------------- */
.section-title {
  font-size: 1.35rem;
  margin-bottom: 1.1rem;
}

/* Pairs a .section-title with a "View all" link on the same line (home
   "New in stock" - templates/shop/home.html) without changing how
   .section-title looks anywhere it's used alone - the row itself carries
   the bottom margin .section-title normally has (the heading inside gets
   .mb-0 to cancel its own), and wraps to two lines gracefully on very
   narrow screens instead of squeezing the link against long text. */
.section-title-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-bottom: 1.1rem;
}

.section-title-link {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--color-accent-deep);
  text-decoration: none;
  white-space: nowrap;
}

.section-title-link:hover {
  /* Stays at the same AA-safe deep gold as the resting state (plain
     --color-accent measures ~2:1 as text on a white page - nowhere near
     readable) and relies on the underline to signal "hovering". */
  color: var(--color-accent-deep);
  text-decoration: underline;
}

.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.75rem;
}

.filter-pill {
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-ink);
  padding: 0.45rem 1rem;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: 0.88rem;
  text-decoration: none;
  transition: all 0.15s ease;
}

.filter-pill.active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #241a00;
}

.filter-pill:not(.active):hover {
  border-color: var(--color-accent);
  color: var(--color-accent-deep);
}

.summary-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 1.25rem 1.4rem;
}

.confirmation-panel {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  max-width: 560px;
  margin: 0 auto;
}

.site-footer {
  /* Black bookend, bottom half - mirrors .site-nav so the light content
     area reads as one page framed top and bottom (see section 3). */
  flex-shrink: 0;
  text-align: center;
  color: rgba(255, 255, 255, 0.6);
  padding: 1.75rem 0;
  border-top: 2px solid var(--color-accent);
  background: var(--color-ink);
}

.site-footer a {
  color: rgba(255, 255, 255, 0.85);
}

.site-footer a:hover {
  color: var(--color-accent);
}

/* --- 9. AI assistant chat widget -------------------------------------------------- */
.assistant-launcher {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 60;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  background: var(--color-accent);
  color: #241a00;
  border: none;
  border-radius: var(--radius-pill);
  padding: 0.85rem 1.25rem;
  font-weight: 700;
  font-size: 0.92rem;
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  transition: transform 0.15s ease, background-color 0.15s ease;
}

.assistant-launcher:hover {
  background: var(--color-accent-dark);
  transform: translateY(-2px);
}

.assistant-launcher svg {
  width: 20px;
  height: 20px;
}

.assistant-panel {
  position: fixed;
  right: 1.25rem;
  bottom: 5.25rem;
  z-index: 60;
  width: min(360px, calc(100vw - 2rem));
  height: min(520px, calc(100vh - 8rem));
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--color-border);
}

.assistant-panel[hidden] {
  display: none;
}

.assistant-header {
  background: linear-gradient(135deg, var(--color-ink), #23262d);
  color: #fff;
  padding: 1rem 1.1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.assistant-header-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  margin: 0;
}

.assistant-header-subtitle {
  font-size: 0.78rem;
  opacity: 0.85;
  margin: 0;
}

.assistant-header-actions {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
}

.assistant-close, .assistant-icon-btn {
  background: rgba(255, 255, 255, 0.15);
  border: none;
  color: #fff;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.assistant-icon-btn svg {
  width: 15px;
  height: 15px;
}

.assistant-close:hover, .assistant-icon-btn:hover {
  background: rgba(255, 255, 255, 0.28);
}

/* --- Menu / quiz chip buttons (the "help me pick a ball" flow) ------------- */
.assistant-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-self: stretch;
  margin: 0.1rem 0 0.3rem;
}

.assistant-chip {
  border: 1px solid var(--color-accent-dark);
  background: #fff;
  color: var(--color-accent-deep);
  font-weight: 600;
  font-size: 0.85rem;
  padding: 0.5rem 0.9rem;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.assistant-chip:hover:not(:disabled) {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #241a00;
}

.assistant-chip:disabled {
  opacity: 0.5;
  cursor: default;
}

/* --- Product recommendation cards (shown after the quiz) -------------------- */
.assistant-product-card {
  display: flex;
  gap: 0.7rem;
  align-self: stretch;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.65rem;
  max-width: 92%;
  text-decoration: none;
  color: inherit;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.assistant-product-card:hover {
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

.assistant-product-card img {
  width: 56px;
  height: 56px;
  object-fit: contain;
  background: var(--color-primary-light);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  padding: 0.3rem;
}

.assistant-product-card-body {
  min-width: 0;
}

.assistant-product-card-name {
  font-weight: 700;
  font-size: 0.86rem;
  color: var(--color-ink);
  margin: 0 0 0.15rem;
}

.assistant-product-card-price {
  font-weight: 700;
  font-size: 0.82rem;
  color: var(--color-accent-deep);
  margin: 0 0 0.2rem;
}

.assistant-product-card-reason {
  font-size: 0.78rem;
  color: var(--color-muted);
  margin: 0;
}

.assistant-product-card-cta {
  display: inline-block;
  margin-top: 0.3rem;
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--color-accent-deep);
}

.assistant-messages {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  background: var(--color-bg);
}

.assistant-msg {
  max-width: 84%;
  padding: 0.55rem 0.85rem;
  border-radius: var(--radius-md);
  font-size: 0.88rem;
  line-height: 1.4;
  white-space: pre-line;
}

.assistant-msg.from-user {
  align-self: flex-end;
  background: var(--color-primary);
  color: #fff;
  border-bottom-right-radius: 4px;
}

.assistant-msg.from-bot {
  align-self: flex-start;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-ink);
  border-bottom-left-radius: 4px;
}

.assistant-msg.from-bot.is-error {
  color: var(--color-danger);
  border-color: rgba(214, 69, 69, 0.35);
}

.assistant-msg.is-typing {
  color: var(--color-muted);
  font-style: italic;
}

.assistant-input-row {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem;
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
  flex-shrink: 0;
}

.assistant-input-row input {
  flex: 1 1 auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: 0.55rem 1rem;
  font-size: 0.88rem;
}

.assistant-input-row input:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 0.15rem var(--color-accent-light);
}

.assistant-send-btn {
  background: var(--color-accent);
  color: #241a00;
  border: none;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.assistant-send-btn:hover {
  background: var(--color-accent-dark);
}

.assistant-send-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

@media (max-width: 420px) {
  .assistant-panel {
    right: 0.5rem;
    left: 0.5rem;
    width: auto;
  }
  .assistant-launcher {
    /* Collapsed to an icon-only circular button on narrow screens. It was
       a ~172px-wide pill with a text label at every size - fine on
       desktop, but on a real phone confirmed via screenshot to sit
       directly on top of (and partly block tapping) whatever form field
       or card happened to scroll underneath its fixed bottom-right
       position, most visibly the last payment method card at checkout.
       Shrinking it to a 52px circle keeps it recognizable (the chat-
       bubble icon is a standard affordance) while cutting its footprint
       by more than two-thirds. The visible label is hidden below;
       aria-label on the button (see _assistant_widget.html) keeps it
       named for screen readers. */
    right: 0.75rem;
    bottom: 0.75rem;
    width: 3.25rem;
    height: 3.25rem;
    padding: 0;
    justify-content: center;
    border-radius: 50%;
  }
  .assistant-launcher span {
    display: none;
  }
}

/* --- 10. Admin product photo management ------------------------------------------- */
.admin-gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
}

.admin-photo-tile {
  position: relative;
  width: 110px;
  cursor: grab;
  touch-action: none;
}

.admin-photo-tile:active {
  cursor: grabbing;
}

.admin-photo-tile img {
  display: block;
  width: 110px;
  height: 110px;
  object-fit: contain;
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.4rem;
  pointer-events: none; /* clicks/drags pass through to the tile itself */
}

.admin-photo-tile.is-dragging {
  opacity: 0.4;
}

.admin-photo-tile.is-marked-removed img {
  border-color: #dc3545;
  opacity: 0.45;
}

/* Position number, top-left - matches the numbered badges in the
   marketplace reference this gallery's interaction is modeled on, and
   doubles as a live preview of the order that will be saved. */
.admin-photo-badge {
  position: absolute;
  top: 0.3rem;
  left: 0.3rem;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(22, 24, 28, 0.82);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  border-radius: var(--radius-pill);
  pointer-events: none;
}

/* Red (not the brand black/gold) - a destructive action (deletes the photo
   file on save), so it's deliberately styled to stand out from every
   other, non-destructive control on this page. */
.admin-photo-delete {
  position: absolute;
  top: 0.3rem;
  right: 0.3rem;
  width: 1.35rem;
  height: 1.35rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: #dc3545;
  color: #fff;
  font-size: 0.85rem;
  line-height: 1;
  padding: 0;
  cursor: pointer;
}

.admin-photo-tile.is-marked-removed .admin-photo-delete {
  background: var(--color-muted);
}

.admin-photo-move-group {
  position: absolute;
  bottom: 0.3rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 0.2rem;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.admin-photo-tile:hover .admin-photo-move-group,
.admin-photo-tile:focus-within .admin-photo-move-group {
  opacity: 1;
}

.admin-photo-move {
  width: 1.35rem;
  height: 1.35rem;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: 0.8rem;
  line-height: 1;
  padding: 0;
  cursor: pointer;
}

.admin-photo-add-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  width: 110px;
  height: 110px;
  border: 1.5px dashed var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-muted);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.admin-photo-add-tile:hover {
  border-color: var(--color-accent);
  color: var(--color-accent-deep);
}

.admin-photo-add-icon {
  font-size: 1.5rem;
  line-height: 1;
}

/* --- 11. Product photo gallery, zoom & lightbox (product detail page) ------------- */
/* Layout: a vertical thumbnail rail beside a big "stage" image on desktop
   (Unisport-style), collapsing to stage-on-top / thumbs-in-a-scrolling-row
   on narrow screens where there's no room for a side rail. The stage
   itself never zooms - clicking/tapping it (or the magnifier button) just
   opens the lightbox (see templates/shop/product_detail.html); zooming
   only happens once that's open, via tap-to-zoom-then-drag-to-pan. That
   lightbox zoom uses an absolutely-positioned layer whose background-image
   is the same photo at a larger background-size, with background-position
   driven by pointer coordinates - rather than transform: scale(), so the
   "magnified" pixels are the browser's own image decode at zoom, not a
   blurry CSS scale-up. */
.product-gallery {
  display: flex;
  gap: 1rem;
}

.product-gallery-thumbs {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  gap: 0.6rem;
  max-height: 30rem;
  overflow-y: auto;
  /* Gives hover/active thumbnails room to lift (see transform below)
     without getting visually clipped by the scroll container's edge. */
  padding: 0.2rem;
}

.product-gallery-thumb {
  flex: 0 0 auto;
  padding: 0;
  width: 4rem;
  height: 4rem;
  /* Transparent by default rather than no border at all - a border that
     only APPEARS on hover/active shifts the thumbnail's box size by
     however thick it is, nudging every thumbnail below it. Reserving the
     space up front with a transparent border means only the color
     changes later, nothing moves. This is also the fix for the biggest
     gap against a clean, modern reference look: a resting gray-boxed
     grid of thumbnails reads as dated next to photos that float with no
     visible frame at all until you interact with them. */
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.product-gallery-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 0.25rem;
}

.product-gallery-thumb:hover {
  border-color: var(--color-accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}

.product-gallery-thumb.is-active {
  border-color: var(--color-accent-dark);
  box-shadow: 0 0 0 0.15rem var(--color-accent-light);
}

.product-gallery-thumb:focus-visible {
  outline: 2px solid var(--color-accent-dark);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .product-gallery-thumb {
    transition: none;
  }
  .product-gallery-thumb:hover {
    transform: none;
  }
}

/* --- Stage: the big image + hover lens + nav arrows + zoom-in button --- */
.product-gallery-stage {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  border-radius: var(--radius-md);
  /* No border, no resting shadow, no boxed-card background - a
     bordered/shadowed "card" around the photo was the single biggest
     thing making this page read as dated next to a reference like
     Unisport's product gallery, where the photo just floats on the
     page with generous whitespace and picks up a shadow only once you
     actually interact with it. overflow: hidden stays - it's not for a
     border edge anymore, it's what keeps the hover scale-up (see
     .product-gallery-zoom-trigger img below) from visually spilling
     past this box's edges. */
  overflow: hidden;
  transition: box-shadow 0.25s ease;
}

.product-gallery-stage:hover {
  box-shadow: var(--shadow-sm);
}

@media (prefers-reduced-motion: reduce) {
  .product-gallery-stage {
    transition: none;
  }
}

.product-gallery-zoom-trigger {
  display: block;
  width: 100%;
  padding: 2rem;
  border: 0;
  background: none;
  cursor: pointer;
}

.product-gallery-zoom-trigger img {
  width: 100%;
  height: auto;
  display: block;
  pointer-events: none;
  /* A hair of scale-up on hover (see .product-gallery-stage:hover below)
     signals "this opens/zooms" the way a static image never can - the
     single biggest cheap win for making a plain product photo feel like
     an interactive modern gallery instead of a flat <img>. */
  transition: transform 0.3s ease;
}

.product-gallery-stage:hover .product-gallery-zoom-trigger img {
  transform: scale(1.03);
}

@media (prefers-reduced-motion: reduce) {
  .product-gallery-zoom-trigger img {
    transition: none;
  }
  .product-gallery-stage:hover .product-gallery-zoom-trigger img {
    transform: none;
  }
}

.product-gallery-zoom-hint {
  position: absolute;
  right: 0.9rem;
  bottom: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-pill);
  background: rgba(22, 24, 28, 0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  color: #fff;
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  transition: transform 0.25s ease, background-color 0.25s ease;
}

.product-gallery-stage:hover .product-gallery-zoom-hint {
  transform: scale(1.1);
  background: var(--color-accent-deep);
}

@media (prefers-reduced-motion: reduce) {
  .product-gallery-zoom-hint {
    transition: none;
  }
  .product-gallery-stage:hover .product-gallery-zoom-hint {
    transform: none;
  }
}

.product-gallery-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  /* Without this, the lightbox variant of this button is invisibly dead:
     .product-lightbox-zoom is also position: relative (needed so its own
     zoom lens can anchor to it) and comes later in the HTML, so with no
     z-index of its own it would paint - and hit-test - on top of these
     nav arrows wherever the two overlap, silently swallowing every click
     even though the arrow is still visibly drawn underneath. */
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;   /* was 2.25rem */
  height: 2.5rem;  /* was 2.25rem */
  border: 0;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(4px);          /* NEW */
  -webkit-backdrop-filter: blur(4px);  /* NEW */
  box-shadow: var(--shadow-md);  /* was --shadow-sm */
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  color: var(--color-ink);
  transition: background-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;  /* NEW */
}

.product-gallery-nav:hover {
  background: #fff;
  color: var(--color-accent-dark);
  transform: translateY(-50%) scale(1.08);  /* NEW */
  box-shadow: var(--shadow-lg);             /* NEW */
}

.product-gallery-nav:focus-visible {   /* NEW RULE */
  outline: 2px solid var(--color-accent-dark);
  outline-offset: 2px;
}

/* On a mouse/trackpad the arrows only appear once you're actually
   hovering the stage - out of the way of the photo the rest of the
   time. Skipped entirely on touch (no hover to gate on), where they'd
   otherwise just vanish with no way to bring them back. */
@media (hover: hover) and (pointer: fine) {
  .product-gallery-nav {
    opacity: 0;
    transition: opacity 0.2s ease, background-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
  }
  .product-gallery-stage:hover .product-gallery-nav,
  .product-gallery-nav:focus-visible {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {   /* NEW BLOCK */
  .product-gallery-nav {
    transition: background-color 0.15s ease;
  }
  .product-gallery-nav:hover {
    transform: translateY(-50%);
  }
}

.product-gallery-nav-prev {
  left: 0.5rem;
}

.product-gallery-nav-next {
  right: 0.5rem;
}

@media (max-width: 767.98px) {
  .product-gallery {
    flex-direction: column-reverse;
  }
  .product-gallery-thumbs {
    flex-direction: row;
    max-height: none;
    overflow-x: auto;
    overflow-y: visible;
  }
}

/* --- Lightbox: full-screen zoomed view, opened from the stage's magnifier --- */
.product-lightbox {
  width: min(92vw, 70rem);
  max-height: 90vh;
  border: 0;
  border-radius: var(--radius-lg);  /* was --radius-md */
  padding: 1rem;
  background: var(--color-surface);
  box-shadow: var(--shadow-lg);

  /* Entrance/exit animation: fades + scales the dialog in and out of the
     top layer instead of the browser default instant show/hide. `overlay`
     and `display` are both discrete properties - allow-discrete is what
     lets a transition run on them at all, and specifically transitioning
     `overlay` is what keeps the dialog painted in the top layer for the
     whole exit transition, instead of it vanishing from the top layer the
     instant .close() removes [open] (which would cut the fade/scale-out
     off before anyone sees it). `overlay` itself only has Chrome/Edge
     support (not Firefox/Safari) - on those browsers this block simply
     has no visible effect and the dialog opens/closes instantly, same as
     before this existed, so nothing needs a JS fallback here. */
  opacity: 0;
  transform: scale(0.92) translateY(0.5rem);
  transition-property: opacity, transform, display, overlay;
  transition-duration: 0.28s;
  transition-timing-function: ease-out;
  transition-behavior: allow-discrete;
}

.product-lightbox[open] {
  opacity: 1;
  transform: scale(1) translateY(0);

  @starting-style {
    opacity: 0;
    transform: scale(0.92) translateY(0.5rem);
  }
}

.product-lightbox::backdrop {
  background-color: rgba(10, 11, 13, 0);
  transition:
    background-color 0.28s ease-out,
    display 0.28s allow-discrete,
    overlay 0.28s allow-discrete;
}

.product-lightbox[open]::backdrop {
  background-color: rgba(10, 11, 13, 0.78);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);

  @starting-style {
    background-color: rgba(10, 11, 13, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .product-lightbox {
    transform: none;
    transition-duration: 0.12s;
  }

  .product-lightbox[open] {
    @starting-style {
      transform: none;
    }
  }
}

.product-lightbox-close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-bg);
  color: var(--color-ink);
  box-shadow: var(--shadow-sm);  /* NEW */
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;  /* NEW */
}

.product-lightbox-close:hover {
  background: var(--color-accent-light);
  color: var(--color-accent-deep);
  transform: rotate(90deg);  /* NEW - a small "close" flourish */
}

.product-lightbox-close:focus-visible {   /* NEW RULE */
  outline: 2px solid var(--color-accent-dark);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {   /* NEW BLOCK */
  .product-lightbox-close {
    transition: background-color 0.15s ease, color 0.15s ease;
  }
  .product-lightbox-close:hover {
    transform: none;
  }
}

.product-lightbox-body {
  display: flex;
  gap: 1rem;
  height: 100%;
}

.product-lightbox-thumbs {
  max-height: min(76vh, 40rem);
}

.product-lightbox-stage {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
}

.product-lightbox-zoom {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  padding: 0;
  background: none;
  cursor: zoom-in;
  overflow: hidden;
}

.product-lightbox-zoom img {
  width: 100%;
  height: min(76vh, 40rem);
  object-fit: contain;
  display: block;
  pointer-events: none;
}

.product-lightbox-zoom-lens {
  /* background-size/-position are set in JS, in real pixels computed
     against the photo's own rendered (object-fit: contain) box rather
     than simple percentages - a percentage-based background-size here
     would stretch and misalign the zoomed crop for any photo whose
     aspect ratio doesn't match this box, which for this catalog's tall
     3:4 product photos is effectively all of them. */
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  opacity: 0;
  pointer-events: none;
}

.product-lightbox-stage.is-zoomed .product-lightbox-zoom img {
  opacity: 0;
}

/* Cursor stays zoom-in even once zoomed, since a tap/click no longer
   turns zoom off (it re-centers to wherever was tapped) - the "Zoom out"
   button below is the only thing that exits zoom, so nothing here should
   look like clicking the photo will un-zoom it. */
.product-lightbox-zoom-reset {
  position: absolute;
  left: 50%;
  bottom: 0.75rem;
  transform: translateX(-50%) translateY(0.5rem);
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.9rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: rgba(22, 24, 28, 0.82);
  color: #fff;
  font-size: 0.85rem;
  white-space: nowrap;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.product-lightbox-stage.is-zoomed .product-lightbox-zoom-reset {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}

.product-lightbox-zoom-reset:hover {
  background: rgba(22, 24, 28, 1);
}

@media (prefers-reduced-motion: reduce) {
  .product-lightbox-zoom-reset {
    transition: none;
  }
}

@media (max-width: 767.98px) {
  .product-lightbox {
    width: 96vw;
  }
  .product-lightbox-body {
    flex-direction: column;
  }
  .product-lightbox-thumbs {
    flex-direction: row;
    max-height: none;
    overflow-x: auto;
    order: 2;
  }
  .product-lightbox-zoom img {
    height: 50vh;
  }
}

/* --- 12. Product description formatting (see formatting.py) ----------------------- */
/* The description text on a product page used to be one flat, unstyled
   paragraph no matter how an admin formatted it - see formatting.py's
   render_description_html for how plain admin-typed text becomes this
   structure (blank-line-separated paragraphs, **bold**, and short
   emoji-led lines promoted to headings). This block is only what makes
   that structure actually LOOK like sections instead of more flat text. */
.product-description {
  margin-bottom: 1rem;
}

.product-description .desc-paragraph {
  color: var(--color-muted);
  line-height: 1.65;
  margin: 0 0 0.85rem;
}

.product-description .desc-paragraph strong {
  color: var(--color-ink);
}

.product-description .desc-heading {
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--color-accent-deep);
  margin: 1.15rem 0 0.4rem;
}

.product-description .desc-heading:first-child {
  margin-top: 0;
}

/* --- 13. Order tracking progress stepper (Track Order page) ----------------------- */
/* Replaces the old plain "Pending"/"Confirmed"/... text badge with a
   visual step-by-step tracker (see templates/shop/track_order.html) - a
   cancelled order never renders this at all (a distinct badge instead),
   since "cancelled" isn't a step ON this path, it's a separate one. */
.order-tracker {
  display: flex;
  align-items: flex-start;
  margin: 0.5rem 0 0.25rem;
}

.order-tracker-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  flex: 0 0 auto;
  width: 5.5rem;
  text-align: center;
}

.order-tracker-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  border: 2px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-muted);
  font-weight: 700;
  font-size: 0.9rem;
  flex-shrink: 0;
}

.order-tracker-label {
  font-size: 0.75rem;
  color: var(--color-muted);
  line-height: 1.2;
}

.order-tracker-line {
  flex: 1 1 auto;
  height: 2px;
  background: var(--color-border);
  margin-top: 1rem;
  min-width: 0.75rem;
}

.order-tracker-line.is-done {
  background: var(--color-primary);
}

.order-tracker-step.is-done .order-tracker-dot {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}

.order-tracker-step.is-done .order-tracker-label {
  color: var(--color-ink);
}

.order-tracker-step.is-current .order-tracker-dot {
  /* Gold, not black - distinct from both the solid-black "done" steps
     and the light-gray "upcoming" ones, so the current step pops instead
     of blending in with steps already completed. --color-accent-deep (not
     -dark) because this is gold text/icon-color sitting on the dot's own
     white fill - -dark alone is only 3.3:1 there and fails WCAG AA. */
  border-color: var(--color-accent-dark);
  color: var(--color-accent-deep);
  box-shadow: 0 0 0 0.15rem var(--color-accent-light);
}

.order-tracker-step.is-current .order-tracker-label {
  color: var(--color-accent-deep);
  font-weight: 600;
}

/* Narrow screens: a horizontal 4-step tracker gets cramped fast, so it
   switches to a vertical list instead - each step's dot lines up in a
   left column with a connecting line running down through it, same
   "done/current/upcoming" coloring as the horizontal version above. */
@media (max-width: 480px) {
  .order-tracker {
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
  }

  .order-tracker-step {
    flex-direction: row;
    align-items: center;
    width: auto;
    text-align: left;
    gap: 0.6rem;
  }

  .order-tracker-label {
    font-size: 0.85rem;
  }

  .order-tracker-line {
    width: 2px;
    height: 1.25rem;
    margin: 0 0 0 0.98rem;
    min-width: 0;
  }
}

/* 14. Admin product analytics (templates/admin/analytics.html) */

/* Chart.js needs an explicit-height parent to size its canvas into -
   without this, a bare <canvas> with no CSS height collapses to a sliver
   a few pixels tall (Chart.js's own default aspect ratio falls apart once
   maintainAspectRatio is turned off in the JS options, which it has to be
   here so the chart can be a sensible height independent of how wide the
   admin panel happens to be). */
.analytics-chart-wrap {
  position: relative;
  height: 420px;
  width: 100%;
}

@media (max-width: 600px) {
  .analytics-chart-wrap {
    height: 320px;
  }
}

.analytics-table th.sortable {
  user-select: none;
}

/* 15. Admin dashboard stat cards - reuses .stat-icon (section 7c above), the
   same icon-circle look as the customer-facing home page's stat row, so the
   admin panel doesn't read as a plain unbranded Bootstrap page bolted onto
   an otherwise-branded storefront. */
.admin-stat-card {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  height: 100%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 1.1rem 1.25rem;
}

.admin-stat-label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-muted);
  margin-bottom: 0.3rem;
}

.admin-stat-value {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--color-ink);
  margin-bottom: 0.15rem;
  line-height: 1.2;
}

.admin-stat-sub {
  font-size: 0.82rem;
  color: var(--color-muted);
  margin-bottom: 0;
}

/* 16. Product card titles (home "New in stock", the shop grid, and "You
   might also like") - a two-line clamp with ellipsis so a long, all-caps,
   emoji-heavy product name (real examples already in the live catalog) can
   never stretch one card taller than its neighbors and break the grid's
   row alignment. The full name is still there for a screen reader and as
   the native title="" tooltip on hover - only the visual line count is
   capped. Standard property included alongside the -webkit- one it needs
   for support in every current browser (Baseline widely available as of
   2024, but this repo doesn't have an explicit newer browser-support
   floor - see modern-web-guidance - so both are kept, at zero cost). */
.card-product-name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
