/*
 * Enter any custom CSS here.
 * This file will not be overwritten by theme updates.
*/

/* Catch-all: prevent rogue horizontal scroll on mobile from off-screen elements
   (hero light beams, glow blobs, transforms, etc). `clip` is safer than `hidden` —
   doesn't create a scroll container so position: sticky still works inside. */
html, body { overflow-x: clip; }

/* ── Scrollbars: hidden everywhere ──
   Scrolling still works (wheel, keys, touch, drag) — only the bar itself is gone.
   Applies to nested scrollers too, e.g. the group modal body. `color-scheme` stays
   so native form controls and any UA chrome keep rendering dark. */
:root { color-scheme: dark; }

html, body, * {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* legacy Edge / IE */
}

::-webkit-scrollbar { width: 0; height: 0; display: none; }  /* Chromium, Safari */

/* ── Shop logo sizing ──
   These MUST live here rather than in a component <style> block. custom.css is
   render-blocking in <head>, so the constraint is known before first paint. A
   <style> at the end of a component is parsed after the <img> above it, which
   lets a full-size shop logo paint across the page for a frame on load. */
.nw-brand-logo {
  height: 30px;
  width: auto;
  border-radius: 8px;
  display: block;
}

.rv-reply-logo {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 8px;
  object-fit: contain;
  background: rgba(var(--cl-accent), 0.14);
}

/* Same reasoning for every other component image. Only the size-critical
   declarations live here; the cosmetic ones stay with their component. */
.rv-thumb {
  width: 34px;
  height: 34px;
  flex: none;
  object-fit: cover;
}

.hero-bg-grid {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: block;
  width: 100%;
  max-width: 1440px;
  height: auto;
  z-index: 1;
}

.hero-dashboard-img {
  display: block;
  width: 100%;
}

/* ── Group popout modal (components/products.njk) ── */
.gp-overlay { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; padding: 32px; }
.gp-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.75); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.gp-panel {
  position: relative; width: 100%; max-width: 1100px;
  max-height: calc(100vh - 64px); max-height: calc(100dvh - 64px);
  display: flex; flex-direction: column;
  border-radius: 16px; background: #121214; border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.6); overflow: hidden;
}
.gp-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 22px 28px; border-bottom: 1px solid rgba(255, 255, 255, 0.06); flex-shrink: 0;
}
.gp-title {
  margin: 0; font-size: 24px; font-weight: 600;
  background: linear-gradient(180deg, #ffffff, #9a9aa3);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.gp-x {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.08);
  cursor: pointer; transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}
.gp-x:hover { color: #f2f2f5; background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.18); }
.gp-body {
  overflow-y: auto; padding: 24px 28px 28px;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  grid-auto-rows: max-content; align-content: start; gap: 16px;
}
.gp-cardwrap { animation: gp-card-in 0.35s ease-out both; }
@keyframes gp-card-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
/* panel enter / leave */
.gp-tr-enter { transition: opacity 0.25s ease-out, transform 0.25s ease-out; }
.gp-tr-enter-start { opacity: 0; transform: translateY(14px) scale(0.975); }
.gp-tr-enter-end { opacity: 1; transform: translateY(0) scale(1); }
.gp-tr-leave { transition: opacity 0.2s ease-in, transform 0.2s ease-in; }
.gp-tr-leave-start { opacity: 1; transform: translateY(0) scale(1); }
.gp-tr-leave-end { opacity: 0; transform: translateY(10px) scale(0.975); }
/* mobile: single column, tighter padding, no 300px min forcing overflow */
@media (max-width: 640px) {
  .gp-overlay { padding: 12px; }
  .gp-panel { max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); }
  .gp-head { padding: 16px 18px; }
  .gp-title { font-size: 20px; }
  .gp-body { padding: 16px 18px 20px; grid-template-columns: 1fr; gap: 14px; }
}

/* ── Navbar currency selector ──
   Choices.js replaces the <select> with its own markup, so the compact pill has to
   be rebuilt here. These override the rounded-full 44px defaults in assets/style.css. */
.currency-selector.lg .choices,
.currency-selector.xs .choices {
  overflow: visible !important;
}

.currency-selector.lg .choices__inner {
  height: 34px !important;
  min-height: 0 !important;
  min-width: 0 !important;
  border-radius: 6px !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  background: rgba(255, 255, 255, 0.025) !important;
  padding: 0 36px 0 16px !important;
  display: flex !important;
  align-items: center !important;
  transition: background 0.2s, border-color 0.2s !important;
}
.currency-selector.lg .choices:hover .choices__inner,
.currency-selector.lg .choices.is-open .choices__inner {
  background: rgba(255, 255, 255, 0.05) !important;
  border-color: rgba(255, 255, 255, 0.20) !important;
}
.currency-selector.lg .choices__inner .choices__list { display: flex !important; align-items: center !important; }
.currency-selector.lg .choices__inner .choices__item {
  max-width: none !important;
  display: flex !important;
  align-items: center !important;
  gap: 4px !important;
  padding: 0 !important;
  font-size: 0.875rem !important;
  font-weight: 500 !important;
  color: rgba(var(--cl-t-primary), 0.75) !important;
}
.currency-selector.lg .choices__list--dropdown { margin-left: 0 !important; margin-top: 4px !important; }
.currency-selector.lg .choices[data-type*='select-one']::after,
.currency-selector.lg .choices[data-type*='select-one'].is-open::after {
  border-color: rgba(255, 255, 255, 0.40) transparent transparent !important;
  right: 14px !important;
  margin-top: -2.5px !important;
  top: 50% !important;
}

/* Mobile (xs) currency selector */
.currency-selector.xs .choices__inner {
  height: 28px !important;
  min-height: 0 !important;
  border-radius: 6px !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  background: rgba(255, 255, 255, 0.025) !important;
  padding: 0 24px 0 8px !important;
  width: 68px !important;
  max-width: 68px !important;
  min-width: 0 !important;
  overflow: hidden !important;
  display: flex !important;
  align-items: center !important;
}
.currency-selector.xs .choices__inner .choices__list { display: flex !important; align-items: center !important; }
.currency-selector.xs .choices__inner .choices__item {
  display: flex !important;
  align-items: center !important;
  gap: 3px !important;
  padding: 0 !important;
  font-size: 0.75rem !important;
  font-weight: 500 !important;
  color: rgba(var(--cl-t-primary), 0.75) !important;
}
.currency-selector.xs .choices__list--dropdown { margin-top: 4px !important; }
.currency-selector.xs .choices[data-type*='select-one']::after,
.currency-selector.xs .choices[data-type*='select-one'].is-open::after {
  border-color: rgba(255, 255, 255, 0.40) transparent transparent !important;
  right: 8px !important;
  margin-top: -2.5px !important;
  top: 50% !important;
}

/* ── Navbar language selector ──
   Only rendered when the shop has more than one language enabled. Matched to the
   currency pill above so the two controls line up. */
.language-selector.lg .choices,
.language-selector.xs .choices {
  overflow: visible !important;
}
.language-selector.lg .choices__inner {
  height: 34px !important;
  min-height: 0 !important;
  min-width: 0 !important;
  border-radius: 6px !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  background: rgba(255, 255, 255, 0.025) !important;
  padding: 0 32px 0 12px !important;
  display: flex !important;
  align-items: center !important;
  transition: background 0.2s, border-color 0.2s !important;
}
.language-selector.lg .choices:hover .choices__inner,
.language-selector.lg .choices.is-open .choices__inner {
  background: rgba(255, 255, 255, 0.05) !important;
  border-color: rgba(255, 255, 255, 0.20) !important;
}
.language-selector.lg .choices__inner .choices__item,
.language-selector.xs .choices__inner .choices__item {
  padding: 0 !important;
  font-size: 0.875rem !important;
  font-weight: 500 !important;
  color: rgba(var(--cl-t-primary), 0.75) !important;
}
.language-selector.lg .choices[data-type*='select-one']::after,
.language-selector.lg .choices[data-type*='select-one'].is-open::after,
.language-selector.xs .choices[data-type*='select-one']::after,
.language-selector.xs .choices[data-type*='select-one'].is-open::after {
  border-color: rgba(255, 255, 255, 0.40) transparent transparent !important;
  right: 12px !important;
  margin-top: -2.5px !important;
  top: 50% !important;
}
.language-selector.xs .choices__inner {
  height: 28px !important;
  min-height: 0 !important;
  border-radius: 6px !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  background: rgba(255, 255, 255, 0.025) !important;
  padding: 0 26px 0 8px !important;
  display: flex !important;
  align-items: center !important;
}
.language-selector .choices__list--dropdown { margin-top: 4px !important; }

/* ── Navbar ──
   Kept here rather than in components/navbar.njk: the bar is above the fold and
   has no data-dsr guard, so component-level <style> would arrive after the markup
   and the nav would paint unstyled for a frame. */
.nw-nav { position: relative; }

  /* Fading background. Sits behind the content so opacity can animate cleanly. */
  .nw-nav-bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: rgba(9, 9, 11, 0.72);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity .4s cubic-bezier(.4, 0, .2, 1), transform .4s cubic-bezier(.4, 0, .2, 1);
  }
  .nw-nav-bg.is-on { opacity: 1; transform: translateY(0); }

  .nw-nav-inner {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    height: 68px;
    width: 100%;
    max-width: 80rem;
    margin: 0 auto;
    padding: 0 1.5rem;
  }
  @media (min-width: 1024px) {
    /* three tracks so the links sit dead-centre regardless of brand / action widths */
    .nw-nav-inner { display: grid; grid-template-columns: 1fr auto 1fr; height: 76px; }
  }

  /* ── Brand ── */
  .nw-brand { display: inline-flex; align-items: center; gap: 10px; justify-self: start; text-decoration: none; }
  /* .nw-brand-logo is sized in assets/custom.css on purpose — that file is
     render-blocking in <head>, so the logo can never paint at full size first. */
  .nw-brand-name {
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: -0.02em;
    color: rgb(var(--cl-t-primary));
    white-space: nowrap;
  }

  /* ── Centre links ── */
  .nw-links { display: none; }
  @media (min-width: 1024px) {
    .nw-links { display: flex; align-items: center; gap: 2.25rem; justify-self: center; }
  }
  .nw-link {
    position: relative;
    font-size: 0.875rem;
    font-weight: 400;
    letter-spacing: -0.01em;
    white-space: nowrap;
    text-decoration: none;
    color: rgba(var(--cl-t-primary), 0.55);
    transition: color .25s ease;
  }
  .nw-link:hover { color: rgb(var(--cl-t-primary)); }
  .nw-link.is-active { color: rgb(var(--cl-t-primary)); }
  /* underline grows from the centre on hover */
  .nw-link::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -6px;
    width: 0;
    height: 1px;
    background: currentColor;
    opacity: .55;
    transform: translateX(-50%);
    transition: width .3s cubic-bezier(.4, 0, .2, 1);
  }
  .nw-link:hover::after { width: 100%; }
  .nw-link.is-active::after { width: 100%; }

  /* ── Right-hand actions ── */
  .nw-actions { display: none; }
  @media (min-width: 1024px) {
    .nw-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; justify-self: end; }
  }

  .nw-icon-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.10);
    background: rgba(255, 255, 255, 0.025);
    color: rgba(var(--cl-t-primary), 0.75);
    transition: color .25s ease, background-color .25s ease, border-color .25s ease;
  }
  .nw-icon-btn:hover {
    color: rgb(var(--cl-t-primary));
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.20);
  }
  .nw-icon-btn--bare { width: auto; height: auto; border: 0; background: none; }
  .nw-cart-count {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 9999px;
    background: rgb(var(--cl-accent));
    color: rgb(var(--cl-t-accent));
    font-size: 0.625rem;
    font-weight: 600;
    line-height: 16px;
    text-align: center;
  }

  .nw-cta {
    display: inline-flex;
    align-items: center;
    height: 34px;
    padding: 0 14px;
    border-radius: 8px;
    background: rgb(var(--cl-accent));
    color: rgb(var(--cl-t-accent));
    font-size: 0.8125rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .25s ease;
  }
  .nw-cta:hover { background: color-mix(in srgb, rgb(var(--cl-accent)) 90%, #fff); }

  .nw-select {
    display: inline-flex;
    align-items: center;
    height: 34px;
    padding: 0 12px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.10);
    background: rgba(255, 255, 255, 0.025);
    color: rgba(var(--cl-t-primary), 0.75);
    font-size: 0.8125rem;
    font-weight: 500;
    outline: none;
    cursor: pointer;
  }
  .nw-select--xs { height: 28px; padding: 0 8px; font-size: 0.75rem; }

  /* ── Mobile ── */
  .nw-mobile { display: flex; align-items: center; gap: 12px; }
  @media (min-width: 1024px) { .nw-mobile { display: none; } }

  .nw-burger {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 34px;
    height: 34px;
    padding: 0 7px;
    border: 0;
    background: none;
    cursor: pointer;
  }
  .nw-burger span {
    display: block;
    height: 1.5px;
    width: 20px;
    border-radius: 2px;
    background: rgba(var(--cl-t-primary), 0.85);
    transition: transform .3s cubic-bezier(.4, 0, .2, 1), opacity .3s ease;
  }
  .nw-burger span.is-x1 { transform: translateY(3.25px) rotate(45deg); }
  .nw-burger span.is-x2 { transform: translateY(-3.25px) rotate(-45deg); }

  .nw-sheet {
    position: absolute;
    top: 100%;
    left: 1rem;
    right: 1rem;
    z-index: 20;
    padding: 1.25rem 1.25rem 1.5rem;
    border-radius: 14px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(15, 15, 18, 0.96);
    -webkit-backdrop-filter: blur(20px);
    backdrop-filter: blur(20px);
    transform-origin: top;
    transform: translateY(-6px) scale(.98);
    opacity: 0;
    visibility: hidden;
    transition: opacity .28s ease, transform .28s cubic-bezier(.4, 0, .2, 1), visibility .28s;
  }
  .nw-sheet.is-open { opacity: 1; visibility: visible; transform: translateY(6px) scale(1); }
  @media (min-width: 1024px) { .nw-sheet { display: none; } }

  .nw-sheet-list { display: flex; flex-direction: column; gap: 1.125rem; margin: 0; padding: 0; list-style: none; }
  .nw-sheet-link {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: none;
    padding: 0;
    font-family: inherit;
    font-size: 0.9375rem;
    font-weight: 400;
    cursor: pointer;
    text-decoration: none;
    color: rgba(var(--cl-t-primary), 0.7);
    transition: color .25s ease;
  }
  .nw-sheet-link:hover, .nw-sheet-link.is-active { color: rgb(var(--cl-t-primary)); }

  @media (prefers-reduced-motion: reduce) {
    .nw-nav-bg, .nw-link, .nw-link::after, .nw-icon-btn, .nw-cta,
    .nw-burger span, .nw-sheet { transition: none; }
  }

/* ── Anchor offset ──
   The header is position:fixed at ~76px tall, so a bare #hash jump parks the
   target's top edge underneath it. scroll-padding-top pushes every fragment
   landing (nav links, browser fragment nav, scrollIntoView) clear of the bar. */
html {
  scroll-padding-top: 92px;
}
@media (max-width: 640px) {
  html { scroll-padding-top: 78px; }
}

/* ── Page ambience ──
   Faint light down the SIDES of a page so a dark, mostly-empty layout is not
   flat. Same white-over-accent pairing the cards use (.ft-sheen + .ft-glow),
   scaled up and kept faint: the white does the lifting and the accent only
   tints it. Deliberately NOT the old blur-[200px] bg-accent-500/50 blob, which
   read as an orange stain rather than light.

   There is deliberately NO wash behind the top of the page. One used to sit
   there and it landed squarely behind the section heading, which read as a glow
   on the title. Headings get their own treatment, and only on the landing page
   (see "Section heading glow" below).

   The three washes sit at different depths and alternate sides so the light
   travels down the page rather than framing it. Their centres are just outside
   the box, so only the inner falloff shows and none of them draws a circle.
   Y radii are in px, not %, or a long page would stretch them into a wash. */
.pg-glow {
  position: absolute;
  z-index: -1;
  /* Extends 96px above the section, behind the sticky header, so the top wash's
     centre is off-screen and the header strip is not left as the one unlit band
     on the page (that hard edge used to read as the navbar having a background). */
  inset: -96px 0 0;
  pointer-events: none;
  /* Three washes: one at the top of the page, one each side.
     Plain px radii only. min() is NOT accepted inside a radial-gradient size:
     using it made the whole background declaration invalid and the glow vanished
     entirely. The mask below is what keeps a short page safe instead. */
  background:
    /* Top of the page. Centre sits on the element's own top edge, which is above
       the viewport, and the radius is short enough that it has faded out before
       it reaches the heading. A longer one pooled directly on the title. */
    radial-gradient(58% 320px at 50% 0, rgba(255, 255, 255, 0.05), transparent 68%),
    radial-gradient(34% 260px at 50% 0, rgba(var(--cl-accent), 0.10), transparent 72%),
    /* left */
    radial-gradient(24% 340px at -5% 40%, rgba(255, 255, 255, 0.032), transparent 70%),
    radial-gradient(18% 280px at -7% 40%, rgba(var(--cl-accent), 0.075), transparent 72%),
    /* right, lower so the two alternate rather than mirror */
    radial-gradient(24% 340px at 105% 74%, rgba(255, 255, 255, 0.032), transparent 70%),
    radial-gradient(18% 280px at 107% 74%, rgba(var(--cl-accent), 0.075), transparent 72%);
  /* Bottom only. On a short page a side wash is taller than the element and
     reaches its bottom edge, which is what turned the left glow into a rectangle.
     The top needs no fade because the element starts above the viewport. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 84%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0, #000 84%, transparent 100%);
}
/* ── Section heading glow ──
   Two parts, because one alone did not do it:
     1. a glow on the letters themselves, which is always correctly placed
        whatever the heading says or how it wraps
     2. a pool of light behind them for the lift
   The pool hangs off the TITLE, not the head wrapper. On the wrapper its centre
   landed between the title and the subtitle, and on a left-aligned heading it
   sat to the left of the text rather than on it.
   Opt in with .hd-title (plus .hd-title--left when the heading is left-aligned);
   the shared title classes below are wired up already.

   LANDING PAGE ONLY. Everything here is scoped under .tpl-shop, set on <body>
   from templateName, so the inner pages keep plain headings. .rv-head and
   .rv-title in particular are shared with the reviews and status pages, which
   is why an unscoped rule leaked onto them.

   1. a whisper on the letters, so the glow tracks the words however they wrap */
.tpl-shop .hd-title,
.tpl-shop .ft-title,
.tpl-shop .cs-title,
.tpl-shop .rv-title,
.tpl-shop .faq-title {
  text-shadow:
    0 0 30px rgba(255, 255, 255, 0.13),
    0 0 64px rgba(var(--cl-accent), 0.20);
}
/* 2. a pool behind the WHOLE head block, not just the title, so the subtitle and
      anything under it (the reviews rating row) sit in the same light. Sized by
      negative inset rather than fixed dimensions, so it grows with the block
      instead of needing a height guessed per section. */
.hd-glow,
.ft-head,
.cs-head,
.rv-head,
.faq-head {
  position: relative;
}
.tpl-shop .hd-glow::before,
.tpl-shop .ft-head::before,
.tpl-shop .cs-head::before,
.tpl-shop .rv-head::before,
.tpl-shop .faq-head::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: -56px -90px -44px;
  pointer-events: none;
  /* 54% not 50%: the pool overhangs 56px above the block and 44px below, so the
     midpoint of the pool is not the midpoint of the text. At 46% the ellipse
     bloomed 111px above the block and only 67px below, and since there is empty
     space above a heading and content below, it read as light sitting above the
     words rather than on them. */
  background:
    radial-gradient(58% 56% at 50% 54%, rgba(255, 255, 255, 0.05), transparent 72%),
    radial-gradient(44% 46% at 50% 54%, rgba(var(--cl-accent), 0.10), transparent 74%);
}
/* left-aligned heads: shift the bright point over the text, not the container */
.tpl-shop .hd-glow--left::before,
.tpl-shop .cs-head::before,
.tpl-shop .faq-head::before {
  background:
    radial-gradient(50% 56% at 26% 54%, rgba(255, 255, 255, 0.05), transparent 72%),
    radial-gradient(38% 46% at 26% 54%, rgba(var(--cl-accent), 0.10), transparent 74%);
}
/* The FAQ and products heads have no max-width, so they stretch to the full
   container (~1500px) while the text inside only runs to ~530px. Sizing the pool
   off the block therefore lit a lot of empty space to the right of the words.
   These two get a pool sized to the TEXT instead: roughly -60 to 600, centred on
   the text rather than the block. The other heads are capped near 700px, which
   is why their block-sized pools already sat on the words. */
.tpl-shop .hd-glow--left::before,
.tpl-shop .faq-head::before {
  right: auto;
  left: -90px;
  /* 860, not 660. Peak alpha is the same whatever the size, so a smaller ellipse
     is not dimmer at its centre, it just holds less area near peak and reads
     fainter. .cs-head gets a 442px horizontal radius off its 884px pool and
     looks right; at 660 these two were on 330 and looked washed out. 860 puts
     them on 430, level with it. */
  width: min(860px, 100%);
  background:
    radial-gradient(50% 56% at 29% 54%, rgba(255, 255, 255, 0.05), transparent 72%),
    radial-gradient(38% 46% at 29% 54%, rgba(var(--cl-accent), 0.10), transparent 74%);
}
@media (max-width: 768px) {
  .tpl-shop .hd-glow::before,
  .tpl-shop .ft-head::before,
  .tpl-shop .cs-head::before,
  .tpl-shop .rv-head::before,
  .tpl-shop .faq-head::before {
    inset: -48px -24px -32px;
  }
}

/* Sides only, no wash behind the top. Used on the homepage below the hero, which
   already has its own lighting and must stay untouched. Three washes alternating
   down the wrapper so the light travels rather than sitting in one place. */
/* .pg-glow--sides is retained only so existing markup keeps working; the base
   class is sides-only now, so it adds nothing. Safe to drop from markup. */

/* Nothing on a narrow viewport: there is no margin either side for the washes to
   sit in, so they would run across the content instead of beside it. */
@media (max-width: 768px) {
  .pg-glow { background: none; }
}

/* ── Reviews: header + card ──
   Shared by components/feedbacks.njk (homepage carousel) and
   components/feedback-page.njk (the /feedback page). Kept here rather than in
   either component so the two cannot drift apart, and because a component
   <style> only loads on the page that renders that component.
   Carousel-only rules (.rv .splide*, arrows, progress) stay in feedbacks.njk. */
  /* shown on both surfaces when the shop has no reviews yet */
  .rv-empty { margin: 0; text-align: center; font-size: 0.9375rem; color: rgba(var(--cl-t-primary), 0.4); }

/* ── Header (centred, matching the reference) ── */
  .rv-head {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 12px;
    max-width: 46rem;
    margin: 0 auto 3rem;
  }
  @media (min-width: 1024px) { .rv-head { margin-bottom: 4rem; } }

  .rv-title {
    margin: 0;
    font-size: clamp(1.75rem, 3.6vw, 2.5rem);
    line-height: 1.12;
    letter-spacing: -0.03em;
    font-weight: 500;
    color: rgb(var(--cl-t-primary));
    text-wrap: balance;
  }
  .rv-sub {
    margin: 0;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: rgba(var(--cl-t-primary), 0.5);
    white-space: pre-line;
  }
  .rv-rating { display: inline-flex; align-items: center; gap: 9px; margin-top: 2px; }
  .rv-rating-stars { display: inline-flex; gap: 2px; }
  .rv-rating-text { font-size: 0.8125rem; color: rgba(var(--cl-t-primary), 0.45); }

  .rv-star { width: 15px; height: 15px; flex: none; color: rgba(var(--cl-t-primary), 0.18); }
  .rv-star.is-on { color: rgb(var(--cl-accent)); }

  /* Carousel-only rules (faded neighbour slides, pre-mount layout) deliberately
     do NOT live here: they belong to components/feedbacks.njk. Putting them in
     this file once made every card on the reviews page render at 32% opacity. */
  /* No height here on purpose: a card is as tall as its own content, so one
     without a reply is shorter than one with. The carousel needs its slides
     matched instead, and sets height:100% itself in components/feedbacks.njk.
     Never put a fixed or full height back on this rule. */
  .rv-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 13px;
    padding: 24px;
    border-radius: 18px;
    border: 1px solid rgba(255, 255, 255, 0.07);
    background: #0b0b0e;
    box-shadow: 0 28px 70px -34px rgba(0, 0, 0, 0.95);
    overflow: hidden;
    isolation: isolate;
    transition: border-color .4s ease;
  }
  .splide__slide.is-active .rv-card { border-color: rgba(255, 255, 255, 0.13); }
  /* resting vs hovered, matching .ft-card and .cs-card elsewhere on the site */
  .rv-card:hover { border-color: rgba(255, 255, 255, 0.13); }

  /* Same sheen + glow pair as .ft-card in features.njk and .cs-card in
     spotlight.njk. Replaces the section-wide accent blob that used to sit behind
     the whole carousel, so the light belongs to each card instead of the page. */
  .rv-sheen {
    position: absolute;
    z-index: -2;
    inset: 0 0 auto 0;
    height: 210px;
    background:
      radial-gradient(circle closest-corner at 30% 0, rgba(255, 255, 255, 0.20), transparent 72%) top / 100% 1px no-repeat,
      radial-gradient(70% 100% at 30% 0%, rgba(255, 255, 255, 0.055), transparent 74%);
  }
  .rv-glow {
    position: absolute;
    z-index: -1;
    right: -30px;
    bottom: -90px;
    width: min(52%, 280px);
    aspect-ratio: 1;
    border-radius: 50%;
    background: rgb(var(--cl-accent));
    opacity: .07;
    filter: blur(90px);
    transition: opacity .5s ease;
  }
  .splide__slide.is-active .rv-card .rv-glow { opacity: .1; }
  .rv-card:hover .rv-glow { opacity: .1; }

  .rv-quote { position: absolute; top: 16px; right: 18px; color: rgba(var(--cl-t-primary), 0.06); }
  .rv-quote svg { width: 44px; height: 44px; display: block; }

  .rv-stars { display: flex; gap: 2px; position: relative; z-index: 1; }

  /* flex:1 lives on the carousel copy only. Here it would stretch the message to
     fill whatever space the tallest sibling created, pushing the footer to the
     bottom and leaving the hole a reply-less card used to show. */
  .rv-msg {
    margin: 0;
    position: relative;
    z-index: 1;
    font-size: 0.9375rem;
    line-height: 1.62;
    color: rgba(var(--cl-t-primary), 0.84);
    /* caps a runaway review; the card still sizes to whatever is left */
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
  }

  /* Shop reply: a threaded response, logo beside the text like a chat message.
     No outer border or connector - the card already has a border, and stacking
     more frames inside it just reads as clutter. */
  .rv-reply {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.035);
  }

  /* .rv-reply-logo is sized in assets/custom.css on purpose — that file is
     render-blocking in <head>, so the logo can never paint at full size first. */
  .rv-reply-logo--fallback {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    color: rgb(var(--cl-accent));
  }

  .rv-reply-body { min-width: 0; }
  .rv-reply-name {
    display: block;
    margin-bottom: 3px;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: rgba(var(--cl-t-primary), 0.85);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .rv-reply-text {
    margin: 0;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: rgba(var(--cl-t-primary), 0.55);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
  }

  .rv-foot {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 11px;
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
  }
  /* size lives in assets/custom.css so it lands before first paint */
  .rv-thumb {
    border-radius: 9px;
    border: 1px solid rgba(255, 255, 255, 0.08);
  }
  .rv-thumb--blank { background: rgba(255, 255, 255, 0.05); display: block; }
  .rv-meta { min-width: 0; }
  .rv-item {
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 500;
    color: rgba(var(--cl-t-primary), 0.85);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .rv-date { margin: 1px 0 0; font-size: 0.6875rem; color: rgba(var(--cl-t-primary), 0.35); }