/* ============================================================
   TrendiestStore — "glow" layer

   The 2026-08 revamp. Everything the reference design asks for
   that the theme did not already have, plus the overrides that
   pull Dawn's stock header, product cards and collection grid
   into line with it.

   WHERE IT SITS. Loaded after ts-tokens / ts-theme / ts-product
   and before ts-mobile — see snippets/ts-stylesheets.liquid.
   That means it beats those three on source order at equal
   specificity, and ts-mobile's phone corrections still beat it.
   Do not reach for !important here; if a rule is not landing,
   check whether the section is loading its own stylesheet from
   its BODY, because a stylesheet_tag inside a section loads
   after everything in <head> and wins every equal tie.

   1rem IS 12px. Dawn sets
   `html { font-size: calc(var(--font-body-scale) * 62.5%) }` and
   `body_scale` is 120, so the root is 12px — NOT 16, and not
   Dawn's stock 10 either. Multiply by 12 before trusting any
   rem value in this file. Where a value has to be exact
   regardless of that setting (icon boxes, gaps, borders) it is
   written in px on purpose.
   ------------------------------------------------------------
    1  Page shell + section furniture
    2  Buttons + pills
    3  Header / navigation
    4  Hero band
    5  Trust strips (features + benefits)
    6  Category grid
    7  Product cards + Add to cart
    8  Promo banner
    9  Gift-pack showcase carousel
   10  Collection / catalog page
   11  Footer
   12  Reduced motion
   ============================================================ */

/* ---------- 1. Page shell + section furniture ---------------- */
body {
  background: var(--ts-bg);
  color: var(--ts-text);
  font-family: var(--font-body-family);
}

.ts-wrap,
.ts-glow-wrap {
  width: 100%;
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: 20px;
}

/* One rhythm for every band on the page. The reference alternates a
   white section against a blush one rather than separating them with
   rules, so sections carry their own ground and their own air. */
.ts-band {
  padding-block: clamp(40px, 5vw, 72px);
}

.ts-band--tint {
  background: var(--ts-bg-2);
}

.ts-band--flush-top {
  padding-top: 0;
}

/* Air above the footer, set once here rather than per section. `main`
   is the only box that sits between the header group and the footer
   group on EVERY template, so this one rule keeps the last section
   (related products, the review widget, the contact panel) off the
   footer's top border everywhere. It is body-ground, so no section's
   own tint is cut.

   NO PADDING ON TOP. A matching gap under the header was tried and
   removed on request — it read as a dead strip rather than as
   separation, because the header already has its own bottom border
   and the leading section brings its own top padding. The header is
   `position: sticky` anyway, so it could never have owned that gap
   itself; a margin on it would scroll away with the bar. */
#MainContent {
  padding-bottom: clamp(30px, 3.6vw, 56px);
}

/* section header: title on the left, "view all" on the right, exactly
   as the reference lays it out */
.ts-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: clamp(18px, 2.4vw, 30px);
}

.ts-head__title {
  margin: 0;
  font-family: var(--font-heading-family);
  font-weight: 700;
  font-size: clamp(1.8rem, 2.4vw, 2.3333rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--ts-text);
}

.ts-head__sub {
  margin: 6px 0 0;
  font-size: 1.2rem;
  color: var(--ts-muted);
}

.ts-head__link {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 1.1333rem;
  font-weight: 600;
  color: var(--ts-brand);
  text-decoration: none;
  white-space: nowrap;
}

.ts-head__link:hover {
  color: var(--ts-brand-700);
}

.ts-head__link svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.25s var(--ts-ease);
}

.ts-head__link:hover svg {
  transform: translateX(3px);
}

/* ---------- 2. Buttons + pills ------------------------------- */
.ts-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 22px;
  border: 1px solid transparent;
  border-radius: var(--ts-r-pill);
  font-family: var(--font-body-family);
  font-size: 1.2rem;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.2s var(--ts-ease), color 0.2s var(--ts-ease),
    border-color 0.2s var(--ts-ease), transform 0.2s var(--ts-ease),
    box-shadow 0.2s var(--ts-ease);
}

.ts-btn svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ts-btn--primary {
  background: var(--ts-brand);
  border-color: var(--ts-brand);
  color: var(--ts-on-brand);
  box-shadow: var(--ts-sh-brand);
}

.ts-btn--primary:hover {
  background: var(--ts-brand-700);
  border-color: var(--ts-brand-700);
  transform: translateY(-2px);
}

.ts-btn--ghost {
  background: #fff;
  border-color: #fff;
  color: var(--ts-brand);
}

.ts-btn--ghost:hover {
  background: #fff;
  color: var(--ts-brand-700);
  transform: translateY(-2px);
}

.ts-btn--outline {
  background: transparent;
  border-color: var(--ts-line-2);
  color: var(--ts-text);
}

.ts-btn--outline:hover {
  border-color: var(--ts-brand);
  color: var(--ts-brand);
}

.ts-btn--lg {
  padding: 15px 28px;
  font-size: 1.2667rem;
}

.ts-btn--sm {
  padding: 9px 16px;
  font-size: 1.0667rem;
}

/* the little capsule above a heading */
.ts-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 16px;
  padding: 7px 15px 7px 12px;
  border-radius: var(--ts-r-pill);
  background: var(--ts-brand-wash);
  color: var(--ts-brand);
  font-size: 1.04rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.ts-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 4px var(--ts-dot-glow);
}

/* ---------- 3. Header / navigation --------------------------- */
.ts-nav {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--ts-nav-bg);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--ts-line);
}

.ts-nav__inner {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 74px;
  padding-block: 10px;
}

.ts-nav__brand {
  flex: none;
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.ts-nav__brand img {
  display: block;
  width: var(--ts-logo-w, 150px);
  height: auto;
}

/* the centred link row */
/* `min-width: 0` IS LOAD-BEARING. A flex item's default `min-width:
   auto` refuses to shrink below its content, and every link in here is
   `white-space: nowrap` — so without it the row simply pushes the tool
   cluster off the right edge of the window instead of getting narrower.
   That is what put the cart pill 86px past the viewport at 1440px. */
.ts-nav__menu {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 1.6vw, 26px);
  list-style: none;
  margin: 0;
  padding: 0;
}

.ts-nav__item {
  position: relative;
}

/* A mega-menu trigger is a <button> and a plain link is an <a>, so this
   has to neutralise the browser's default button chrome or the two sit
   side by side looking like different components — which is exactly how
   "Categories" and "Gift Packs" ended up drawn in boxes. */
.ts-nav__link {
  appearance: none;
  background: none;
  border: 0;
  font-family: inherit;
  /* AND line-height, WHICH IS THE ONE THAT WAS MISSING. The UA sheet
     styles a button with the `font` SHORTHAND, and a shorthand resets
     every part it does not mention — so `line-height` went back to
     `normal` on the two <button> triggers while the <a> links inherited
     the body's 1.667. That is 31px tall against 38px: "Categories" and
     "Gift Packs" sat 1.5px lower than "Home", "All Products" and
     "Contact", and the active underline (::after, bottom:0 of the
     .ts-nav__item) sat 7px higher on them. Setting font-family without
     line-height fixes half of a button's inherited type and leaves the
     other half at the browser's default. */
  line-height: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 8px 2px;
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--ts-text-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s var(--ts-ease);
}

.ts-nav__link:hover,
.ts-nav__item--active .ts-nav__link {
  color: var(--ts-brand);
}

/* the active tab keeps the short underline the reference draws */
.ts-nav__link::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--ts-brand);
  transform: translateX(-50%);
  transition: width 0.25s var(--ts-ease);
}

.ts-nav__link:hover::after,
.ts-nav__item--active .ts-nav__link::after {
  width: 22px;
}

.ts-nav__caret {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.22s var(--ts-ease);
}

.ts-nav__item[data-open='true'] .ts-nav__caret {
  transform: rotate(180deg);
}

/* ---- mega menu ------------------------------------------------
   Hidden with `display:none`, NOT visibility/opacity. A panel that is
   only transparent still counts as in-viewport, so every category
   thumbnail inside it would be fetched on page load for a menu almost
   nobody opens — the same trap the product zoom modal had. */
.ts-mega {
  display: none;
  position: absolute;
  top: calc(100% + 14px);
  left: 50%;
  transform: translateX(-50%);
  width: min(92vw, 760px);
  padding: 22px;
  border: 1px solid var(--ts-line);
  border-radius: var(--ts-r-lg);
  background: var(--ts-nav-menu-bg);
  box-shadow: var(--ts-sh-3);
}

.ts-nav__item[data-open='true'] .ts-mega {
  display: block;
  animation: ts-mega-in 0.2s var(--ts-out);
}

@keyframes ts-mega-in {
  from {
    opacity: 0;
    transform: translateX(-50%) translateY(-6px);
  }
}

/* THE 14px GAP ABOVE THE PANEL BELONGS TO NEITHER BOX. The panel is a
   child of the nav item, so hovering it keeps the item hovered — but
   the space the panel is offset by is outside both, so a pointer
   travelling down from the link left the item and `pointerleave`
   closed the menu before it ever arrived. A transparent bridge across
   that gap keeps the pointer inside the item for the whole journey.
   ts-theme.js adds a short close delay on top of this so a diagonal
   path to a far corner is forgiving too — the bridge alone only fixes
   a straight-down move. Desktop only: below 990px the panel is
   `position: static` inside the drawer and this would be nonsense. */
@media screen and (min-width: 990px) {
  .ts-mega::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    /* exactly the 14px offset above, no more: an over-long bridge
       would overlap the trigger's own box and swallow clicks on it,
       because a pseudo-element hit-tests as its host (.ts-mega). */
    top: -14px;
    height: 14px;
  }
}

.ts-mega__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px 14px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.ts-mega__link {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 10px;
  border-radius: var(--ts-r-sm);
  color: var(--ts-text-2);
  font-size: 1.16rem;
  text-decoration: none;
  transition: background-color 0.18s var(--ts-ease), color 0.18s var(--ts-ease);
}

.ts-mega__link:hover {
  background: var(--ts-bg-3);
  color: var(--ts-brand);
}

.ts-mega__thumb {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  object-fit: cover;
  background: var(--ts-bg-3);
}

.ts-mega__count {
  margin-left: auto;
  font-size: 1rem;
  color: var(--ts-muted-2);
}

.ts-mega__all {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--ts-line);
  width: 100%;
  font-size: 1.1333rem;
  font-weight: 600;
  color: var(--ts-brand);
  text-decoration: none;
}

/* ---- the right-hand controls ---------------------------------- */
.ts-nav__tools {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.ts-search {
  display: flex;
  align-items: center;
  width: clamp(180px, 20vw, 260px);
  padding: 4px 4px 4px 16px;
  border: 1px solid var(--ts-line);
  border-radius: var(--ts-r-pill);
  background: #fff;
  transition: border-color 0.2s var(--ts-ease), box-shadow 0.2s var(--ts-ease);
}

.ts-search:focus-within {
  border-color: var(--ts-brand);
  box-shadow: 0 0 0 3px var(--ts-brand-wash);
}

.ts-search input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font-family: inherit;
  font-size: 1.1067rem;
  color: var(--ts-text);
}

.ts-search input::placeholder {
  color: var(--ts-muted-2);
}

.ts-search__go {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background: var(--ts-brand);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.2s var(--ts-ease);
}

.ts-search__go:hover {
  background: var(--ts-brand-700);
}

.ts-search__go svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
}

.ts-icon-btn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ts-text-2);
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.2s var(--ts-ease), color 0.2s var(--ts-ease);
}

.ts-icon-btn:hover {
  background: var(--ts-bg-3);
  color: var(--ts-brand);
}

.ts-icon-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* the cart is a filled pink pill with a count, as in the reference */
.ts-cart-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 15px;
  border-radius: var(--ts-r-pill);
  background: var(--ts-brand);
  color: #fff;
  font-size: 1.1333rem;
  font-weight: 600;
  text-decoration: none;
  transition: background-color 0.2s var(--ts-ease);
}

.ts-cart-pill:hover {
  background: var(--ts-brand-700);
  color: #fff;
}

/* The pill is the whole confirmation for an add now — see the note on
   `.ts-pcard__add.is-added` in ts-fixes.css §4 — so the count has to be
   seen MOVING rather than found afterwards. One short bump, added by
   assets/js/ts-shop.js and removed when it finishes, and nothing at all
   for a visitor who has asked their system for less motion. */
@media (prefers-reduced-motion: no-preference) {
  .ts-cart-pill.is-bumped {
    animation: ts-pill-bump 0.42s var(--ts-ease);
  }
}

@keyframes ts-pill-bump {
  0% { transform: scale(1); }
  35% { transform: scale(1.09); }
  100% { transform: scale(1); }
}

.ts-cart-pill svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The drawer's backdrop. Never painted on desktop — ts-mobile.css turns
   it on under 990px, where it is also given its fixed position. */
.ts-scrim {
  display: none;
}

/* The drawer's search row lives in the same <ul> as the links, so it
   has to be taken out of the desktop link row explicitly or it renders
   a second search pill in the middle of the bar. */
.ts-nav__searchrow {
  display: none;
}

/* DESKTOP-ONLY HIDE, AND THE MEDIA QUERY IS THE WHOLE POINT.

   Written unscoped, this rule is copied verbatim into
   snippets/ts-critical.liquid — which is an INLINE <style> and
   therefore lands after the <link> to ts-mobile.css. ts-mobile's
   `@media (max-width: 989px) { .ts-burger { display: grid } }` has the
   same specificity and loses the tie, so the phone got a nav drawer it
   had no way to open. Scoped to min-width:990 the critical copy simply
   does not match on a phone, and `.ts-icon-btn`'s own `display: grid`
   carries the button. */
@media screen and (min-width: 990px) {
  .ts-burger {
    display: none;
  }
}

/* ---------- 4. Hero band ------------------------------------- */
.ts-hero {
  position: relative;
  padding-block: clamp(16px, 2vw, 26px) 0;
  background: var(--ts-bg);
}

.ts-hero__card {
  position: relative;
  overflow: hidden;
  border-radius: clamp(20px, 2.6vw, 34px);
  background: var(--ts-grad);
  color: #fff;
}

/* the soft petal wash — a gradient, deliberately not a blur filter */
.ts-hero__card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(52% 62% at 82% 22%, rgba(255, 255, 255, 0.22), transparent 70%),
    radial-gradient(38% 48% at 12% 88%, rgba(255, 255, 255, 0.14), transparent 70%);
}

.ts-hero__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
  align-items: center;
  gap: clamp(20px, 3vw, 48px);
  padding: clamp(28px, 4vw, 60px) clamp(22px, 3.4vw, 56px);
}

.ts-hero__eyebrow {
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
}

.ts-hero__title {
  margin: 0 0 16px;
  font-family: var(--font-heading-family);
  font-weight: 700;
  font-size: clamp(2.5333rem, 4.4vw, 4.4rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
}

.ts-hero__title em {
  font-style: normal;
  color: var(--ts-cream);
}

.ts-hero__sub {
  margin: 0 0 26px;
  max-width: 46ch;
  font-size: clamp(1.2rem, 1.2vw, 1.3333rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.9);
}

.ts-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 26px;
}

.ts-hero .ts-btn--primary {
  background: var(--ts-brand-700);
  border-color: var(--ts-brand-700);
  box-shadow: 0 12px 26px -14px rgba(0, 0, 0, 0.5);
}

.ts-hero .ts-btn--primary:hover {
  background: #8d0d4b;
  border-color: #8d0d4b;
}

.ts-hero__stats {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(16px, 3vw, 38px);
  margin: 0;
}

.ts-hero__stats div {
  min-width: 0;
}

.ts-hero__stats dt {
  font-family: var(--font-heading-family);
  font-weight: 700;
  font-size: clamp(1.4rem, 1.8vw, 1.8667rem);
  line-height: 1.2;
  color: #fff;
}

.ts-hero__stats dd {
  margin: 2px 0 0;
  font-size: 1.0133rem;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.82);
}

.ts-hero__was {
  margin-right: 6px;
  font-size: 0.8em;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.62);
}

/* the round "100% Original" seal */
/* TOP right, not bottom right. At the bottom it sat on top of the
   build's step caption, which ends on a product name and runs to two
   lines. Up here it is clear of both columns at every width. */
.ts-hero__seal {
  position: absolute;
  right: clamp(8px, 2vw, 28px);
  top: clamp(12px, 2.4vw, 28px);
  z-index: 2;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 1px;
  box-sizing: border-box;
  /* THE FLOOR IS SET BY THE LABEL, NOT BY TASTE. 9vw only reaches the
     108px ceiling at ~1200px; from 750px down to ~955px the clamp sits
     on its floor, and at the old 78px the padded box left 58px for a
     word that measures 58.6 — "Products" printed over the white edge.
     86px is the smallest disc the two-line label fits inside at this
     font size. Below 750px ts-mobile.css takes over with a smaller
     disc AND a smaller label; both have to move together. */
  width: clamp(86px, 9vw, 108px);
  aspect-ratio: 1;
  /* A circle's usable width shrinks as you move away from its middle,
     so a label sized against the full box overruns the white edge.
     The padding is what holds the two words inside the curve. */
  padding: 10px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--ts-sh-2);
  text-align: center;
}

.ts-hero__seal b {
  font-family: var(--font-heading-family);
  font-size: clamp(1.2667rem, 1.4vw, 1.6667rem);
  font-weight: 700;
  color: var(--ts-brand);
}

.ts-hero__seal span {
  font-size: 1rem;
  line-height: 1.25;
  color: var(--ts-muted);
}

/* ---------- 5. Trust strips ---------------------------------- */
/* The features card rides up over the bottom of the hero, so its own
   band has no top padding and a negative pull. */
.ts-trust {
  position: relative;
  z-index: 2;
}

.ts-trust--overlap {
  margin-top: clamp(-40px, -3.4vw, -26px);
}

.ts-trust__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  padding: clamp(16px, 2vw, 24px) clamp(10px, 2vw, 26px);
  border-radius: var(--ts-r-lg);
  background: var(--ts-bg-3);
  box-shadow: var(--ts-sh-1);
}

.ts-trust--plain .ts-trust__row {
  background: var(--ts-bg-2);
  box-shadow: none;
}

.ts-trust__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-inline: clamp(8px, 1.4vw, 18px);
}

.ts-trust__item + .ts-trust__item {
  border-left: 1px solid var(--ts-line);
}

.ts-trust__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: #fff;
  color: var(--ts-brand);
}

.ts-trust__icon svg {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ts-trust__text b {
  display: block;
  font-size: 1.1467rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ts-text);
}

.ts-trust__text span {
  display: block;
  margin-top: 2px;
  font-size: 1rem;
  line-height: 1.35;
  color: var(--ts-muted);
}

/* ---------- 6. Category grid --------------------------------- */
/* COLUMN COUNTS, AND WHY THEY ARE INDIRECTED THROUGH `--cols`.

   The section writes its desktop count as an INLINE custom property
   (`style="--ts-cat-cols: 5"`). An inline declaration beats every rule
   in every stylesheet, media query or not — so a `@media (max-width:
   620px) { :root { --ts-cat-cols: 1 } }` never applied and the phone
   kept rendering five columns squeezed to 60px each.

   So the inline value is only ever READ, here, into a second property.
   The phone override then re-declares `--cols` on this same element,
   which is an ordinary rule beating an ordinary rule, and it lands. */
.ts-cats {
  --cols: var(--ts-cat-cols, 5);
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}

.ts-cat {
  display: block;
  border-radius: var(--ts-r);
  background: var(--ts-surface);
  text-decoration: none;
  overflow: hidden;
  transition: transform 0.25s var(--ts-ease), box-shadow 0.25s var(--ts-ease);
}

.ts-cat:hover {
  transform: translateY(-4px);
  box-shadow: var(--ts-sh-2);
}

.ts-cat__media {
  /* SPANS INSIDE AN <a>. Anchors may not contain block-level children,
     so every part of these tiles is a <span> — and an inline span has no
     box, so `aspect-ratio`, `padding` and `overflow` are all ignored
     until it is made a block. That is why the category tiles rendered as
     bare images with no label strip. Same for the pack cards below. */
  display: block;
  position: relative;
  aspect-ratio: 1;
  background: var(--ts-bg-3);
  overflow: hidden;
}

.ts-cat__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.45s var(--ts-ease);
}

.ts-cat:hover .ts-cat__media img {
  transform: scale(1.05);
}

.ts-cat__body {
  display: block;
  padding: 12px 10px 14px;
  text-align: center;
  background: #fff;
  border: 1px solid var(--ts-line);
  border-top: 0;
  border-radius: 0 0 var(--ts-r) var(--ts-r);
}

.ts-cat__name {
  display: block;
  font-size: 1.1333rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ts-text);
}

.ts-cat__count {
  display: block;
  margin-top: 3px;
  font-size: 1rem;
  color: var(--ts-muted);
}

/* ---------- 7. Product cards --------------------------------- */
/* see the note on .ts-cats above — same indirection, same reason */
/* THE LIST RESET IS LOAD-BEARING. `ts-row` renders this class on a
   <div>, but sections/related-products.liquid renders it on a <ul> with
   <li> children — and nothing in base.css resets a bare <ul>. So "You
   may also like" was drawn with visible bullets and the UA's 40px
   `padding-inline-start`, which pushed every card 40px right of the
   page gutter and squeezed the column enough to clip the compare-at
   price off the end of the card. */
.ts-products {
  --cols: var(--ts-cols, 5);
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ts-products > li {
  list-style: none;
}

.ts-pcard {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--ts-line);
  border-radius: var(--ts-r);
  background: #fff;
  overflow: hidden;
  transition: transform 0.25s var(--ts-ease), box-shadow 0.25s var(--ts-ease),
    border-color 0.25s var(--ts-ease);
}

.ts-pcard:hover {
  transform: translateY(-4px);
  border-color: var(--ts-line-2);
  box-shadow: var(--ts-sh-2);
}

.ts-pcard__media {
  position: relative;
  display: block;
  aspect-ratio: 1;
  background: var(--ts-bg-2);
  overflow: hidden;
}

.ts-pcard__media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 10px;
  transition: transform 0.45s var(--ts-ease);
}

/* Keep the complete product visible in the catalogue. Enlarging a
   portrait or landscape shot on hover cuts its edges off inside the
   square card frame. */
.ts-pcard__media img,
.ts-pcard:hover .ts-pcard__media img,
.ts-pcard:focus-within .ts-pcard__media img {
  transform: none;
}

.ts-pcard__badge {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
  padding: 4px 10px;
  border-radius: var(--ts-r-pill);
  background: var(--ts-badge-bg);
  color: var(--ts-badge-ink);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.ts-pcard__badge--out {
  background: var(--ts-muted);
}

.ts-pcard__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  gap: 5px;
  padding: 12px 12px 14px;
}

.ts-pcard__title {
  margin: 0;
  font-size: 1.1333rem;
  font-weight: 600;
  line-height: 1.35;
  /* Product titles on this store are long SEO strings and they are the
     merchant's — they are clamped to two lines here, never truncated in
     the data. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ts-pcard__title a {
  color: var(--ts-text);
  text-decoration: none;
}

.ts-pcard__title a:hover {
  color: var(--ts-brand);
}

.ts-pcard__meta {
  font-size: 1rem;
  color: var(--ts-muted);
}

.ts-pcard__rating {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 1rem;
  color: var(--ts-muted);
}

.ts-stars {
  display: inline-flex;
  gap: 1px;
  color: var(--ts-star);
}

.ts-stars svg {
  width: 12px;
  height: 12px;
  fill: currentColor;
}

.ts-stars svg.is-empty {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  opacity: 0.45;
}

.ts-pcard__price {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: auto;
  padding-top: 4px;
  font-family: var(--font-heading-family);
  font-size: 1.3333rem;
  font-weight: 700;
  color: var(--ts-text);
}

.ts-pcard__was {
  font-size: 1.0667rem;
  font-weight: 500;
  color: var(--ts-muted-2);
  text-decoration: line-through;
}

/* This is a <button> on a simple product and an <a> ("Choose options")
   on one with variants, so it has to look identical either way — the
   anchor was picking up the theme's link underline. */
.ts-pcard__add {
  text-decoration: none;
  appearance: none;
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  margin-top: 10px;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--ts-r-sm);
  background: var(--ts-brand);
  color: #fff;
  font-family: inherit;
  font-size: 1.0667rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.2s var(--ts-ease);
}

.ts-pcard__add:hover:not([disabled]) {
  background: var(--ts-brand-700);
}

.ts-pcard__add[disabled] {
  background: var(--ts-bg-3);
  color: var(--ts-muted);
  cursor: not-allowed;
}

.ts-pcard__add svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ts-pcard__add.is-busy {
  opacity: 0.72;
  pointer-events: none;
}

/* ---------- 8. Promo banner ---------------------------------- */
.ts-promo {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: center;
  overflow: hidden;
  border-radius: var(--ts-r-lg);
  background: var(--ts-grad);
  color: #fff;
}

.ts-promo__media {
  position: relative;
  min-height: 100%;
}

.ts-promo__media img {
  display: block;
  width: 100%;
  height: 100%;
  max-height: 260px;
  object-fit: cover;
  object-position: left center;
}

.ts-promo__body {
  padding: clamp(22px, 3vw, 40px) clamp(20px, 3vw, 48px);
}

.ts-promo__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 8px;
  font-size: 1.04rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.9);
}

.ts-promo__eyebrow svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
}

.ts-promo__title {
  margin: 0 0 6px;
  font-family: var(--font-heading-family);
  font-size: clamp(2rem, 3.2vw, 3.2rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
}

.ts-promo__sub {
  margin: 0 0 18px;
  font-size: 1.2rem;
  color: rgba(255, 255, 255, 0.88);
}

/* banner-only: the artwork is the whole message, so the band is just a
   rounded, clickable image */
.ts-promo--full {
  display: block;
  background: none;
  line-height: 0;
}

.ts-promo--full img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--ts-r-lg);
}

/* ---------- 9. Gift-pack showcase carousel ------------------- */
/* The five surprise cups and the Candy Glam pouch, given their own
   band rather than being mixed into the ordinary product grid — they
   are the only things the store makes itself. */
.ts-packs {
  position: relative;
}

.ts-packs__rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(224px, 1fr);
  gap: clamp(12px, 1.4vw, 18px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-bottom: 4px;
  /* the cards lift on hover, and an overflow container would clip the
     shadow -- give it room rather than turning the lift off */
  margin-inline: -6px;
  padding-inline: 6px;
}

.ts-packs__rail::-webkit-scrollbar {
  display: none;
}

.ts-packs__card {
  scroll-snap-align: start;
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: var(--ts-r);
  background: var(--ts-pack-tint, var(--ts-bg-2));
  overflow: hidden;
  text-decoration: none;
  transition: transform 0.25s var(--ts-ease), box-shadow 0.25s var(--ts-ease);
}

.ts-packs__card:hover {
  transform: translateY(-4px);
  box-shadow: var(--ts-sh-2);
}

.ts-packs__media {
  display: block;
  aspect-ratio: 4 / 5;
  padding: 14px;
}

.ts-packs__media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.ts-packs__body {
  display: block;
  padding: 0 14px 16px;
  text-align: center;
}

.ts-packs__name {
  display: block;
  font-size: 1.1333rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ts-text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ts-packs__tag {
  display: block;
  margin-top: 4px;
  font-size: 1rem;
  color: var(--ts-muted);
}

.ts-packs__price {
  display: block;
  margin-top: 8px;
  font-family: var(--font-heading-family);
  font-size: 1.2667rem;
  font-weight: 700;
  color: var(--ts-pack-accent, var(--ts-brand));
}

.ts-packs__nav {
  display: flex;
  gap: 8px;
}

.ts-packs__btn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--ts-line);
  border-radius: 50%;
  background: #fff;
  color: var(--ts-text-2);
  cursor: pointer;
  transition: background-color 0.2s var(--ts-ease), color 0.2s var(--ts-ease),
    border-color 0.2s var(--ts-ease);
}

.ts-packs__btn:hover:not([disabled]) {
  border-color: var(--ts-brand);
  background: var(--ts-brand);
  color: #fff;
}

.ts-packs__btn[disabled] {
  opacity: 0.35;
  cursor: default;
}

.ts-packs__btn svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- 9b. Product page buy block ----------------------- */
/* Dawn styles "Add to cart" with the SECONDARY button tokens and leaves
   the filled treatment for the dynamic "Buy it now" payment button. On
   this design that reads backwards — the cart button is the one the
   whole page is built around, and it was rendering as a white outline
   under a solid pink one. `section-main-product.css` is loaded from the
   product section's body, so it lands after everything in <head>; these
   carry `product-form` to out-specify it rather than relying on order. */
product-form .product-form__submit,
.product-form__buttons .product-form__submit {
  background: var(--ts-brand);
  border-color: var(--ts-brand);
  color: var(--ts-on-brand);
  box-shadow: var(--ts-sh-brand);
}

product-form .product-form__submit:hover:not([disabled]),
.product-form__buttons .product-form__submit:hover:not([disabled]) {
  background: var(--ts-brand-700);
  border-color: var(--ts-brand-700);
}

product-form .product-form__submit::after,
.product-form__buttons .product-form__submit::after {
  box-shadow: none;
}

/* the payment button becomes the quieter of the two */
.product-form__buttons .shopify-payment-button__button--unbranded {
  background: #fff;
  color: var(--ts-brand);
  border: 1px solid var(--ts-line-2);
}

.product-form__buttons .shopify-payment-button__button--unbranded:hover:not([disabled]) {
  background: var(--ts-bg-3);
  color: var(--ts-brand-700);
}

/* ---------- 10. Collection / catalog page -------------------- */
.ts-collhead {
  padding-block: clamp(22px, 3vw, 40px) clamp(16px, 2vw, 26px);
  background: var(--ts-bg-2);
}

.ts-collhead__inner {
  display: grid;
  gap: 10px;
}

.ts-collhead__title {
  margin: 0;
  font-family: var(--font-heading-family);
  font-size: clamp(2.1333rem, 3.2vw, 3.0667rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.ts-collhead__count {
  font-size: 1.0933rem;
  color: var(--ts-muted-2);
}

/* THE CATEGORY CHIP RAIL IS GONE. `.ts-chiprail` and `.ts-chip` were
   the strip of category pills under the collection header; the list
   moved into the filter panel — see woocommerce/archive-product.php —
   and these rules were deleted rather than left behind, because a rule
   nobody renders is a rule that wins a tie the next time somebody
   picks the same class name. Check ts-mobile.css if a stray chip
   ever turns up. */

/* Dawn's own collection grid, pulled onto the card design above.
   These carry `.ts-collection` from the section wrapper so they cannot
   leak into the cart drawer or the search results. */
.ts-collection .product-grid {
  --cols: var(--ts-cols, 4);
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* `.grid__item` pins its own width for Dawn's flex grid and a grid item
   still obeys it, so it has to be reset explicitly or every card comes
   out at Dawn's percentage regardless of the track sizing. */
.ts-collection .product-grid > .grid__item {
  width: auto;
  max-width: none;
  padding: 0;
}

/* ---------- 11. Footer --------------------------------------- */
.ts-foot {
  background: var(--ts-footer-bg);
  border-top: 1px solid var(--ts-line);
}

.ts-foot__grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, minmax(0, 1fr));
  gap: clamp(22px, 3vw, 44px);
  padding-block: clamp(32px, 4vw, 54px);
}

.ts-foot__brand img {
  width: 150px;
  height: auto;
  margin-bottom: 14px;
}

.ts-foot__blurb {
  max-width: 34ch;
  font-size: 1.1333rem;
  line-height: 1.65;
  color: var(--ts-muted);
}

.ts-foot__title {
  margin: 0 0 12px;
  font-size: 1.1333rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--ts-text);
}

.ts-foot__list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ts-foot__list a {
  font-size: 1.12rem;
  color: var(--ts-muted);
  text-decoration: none;
  transition: color 0.18s var(--ts-ease);
}

.ts-foot__list a:hover {
  color: var(--ts-brand);
}

.ts-foot__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-block: 16px;
  border-top: 1px solid var(--ts-line);
  font-size: 1.04rem;
  color: var(--ts-muted-2);
}

.ts-foot__social {
  display: flex;
  gap: 8px;
}

.ts-foot__social a {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: #fff;
  color: var(--ts-brand);
  transition: background-color 0.2s var(--ts-ease), color 0.2s var(--ts-ease);
}

.ts-foot__social a:hover {
  background: var(--ts-brand);
  color: #fff;
}

.ts-foot__social svg {
  width: 17px;
  height: 17px;
}

/* ---------- 12. Reduced motion ------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .ts-cat,
  .ts-cat__media img,
  .ts-pcard,
  .ts-pcard__media img,
  .ts-packs__card,
  .ts-btn,
  .ts-head__link svg {
    transition: none;
  }

  .ts-cat:hover,
  .ts-pcard:hover,
  .ts-packs__card:hover,
  .ts-btn--primary:hover,
  .ts-btn--ghost:hover {
    transform: none;
  }

  .ts-nav__item[data-open='true'] .ts-mega {
    animation: none;
  }
}
