/**
 * Govindani Magic Suite — storefront.
 *
 * Tokens first so a merchant can rebrand the whole listing by overriding a
 * handful of custom properties in their theme, without touching this file.
 */

/* The card is on this list, and that is the important entry.
   ---------------------------------------------------------------------------
   These properties used to be declared on the containers only, and a card was
   assumed to be inside one of them. It is not: the same card is rendered into
   the home carousels, "You may also like", the picked-products grid and the
   no-results suggestions, none of which were listed here.

   An unset custom property does not fall back to something sensible — it makes
   the whole declaration invalid. So `background: var(--gms-ink)` resolved to
   nothing while `color: #fff` stayed literal, and Add to cart rendered as white
   text on a transparent background. On the home carousels the button was there,
   was clickable, and could not be seen at all.

   Declaring them on .gms-card-p as well makes a card self-sufficient wherever
   it is dropped, which is the only way this stops recurring every time a card
   gains a new home. */
.gms-listing,
/* .gms-join is the membership page. Its Join button paints its background from
   --gms-ink, and with the token unset there the declaration was discarded
   entirely: white text on nothing, which the merchant reported as "there is no
   way to buy this membership". */
.gms-drawer,
.gms-filters,
.gms-cartbar,
.gms-delivery-check,
.gms-card-p,
.gms-rail,
.gms-cats,
.gms-picked,
.gms-empty-more,
.gms-pdp__related,
.gms-cmptray,
.gms-cmp-page,
.gms-join {
  --gms-ink:       #14161a;
  --gms-ink-2:     #5b6270;
  --gms-ink-3:     #6b7280;
  --gms-line:      rgba(20, 22, 26, .1);
  --gms-line-2:    rgba(20, 22, 26, .06);
  --gms-surface:   #fff;
  --gms-tint:      #f4f6f8;
  --gms-accent:    #2563eb;
  --gms-accent-ink:#fff;
  --gms-good:      #067647;
  --gms-warn:      #b54708;
  --gms-bad:       #b42318;
  --gms-r:         14px;
  --gms-r-lg:      20px;
  --gms-r-pill:    999px;
  --gms-shadow:    0 1px 2px rgba(16, 24, 40, .04), 0 4px 16px rgba(16, 24, 40, .06);
  --gms-shadow-lg: 0 12px 32px rgba(16, 24, 40, .14);
}

.gms-listing * { box-sizing: border-box; }

/* Icon controls hold their own box, whatever the theme does to <button>.

   Every one of these is a fixed square or circle with a 16px glyph centred in
   it, and every one of them sits inside somebody else's stylesheet. Themes
   style bare <button> globally and shop themes style it generously — the one
   this was written against applies 16px 32px padding to every button on the
   page. That turned the 32px wishlist circle into a 64x32 ellipse with the
   heart shoved off centre, and it clipped the quantity stepper's minus, number
   and plus clean out of their tracks, leaving an empty outlined rectangle where
   Add to cart had been.

   Neither looked like a CSS collision. They looked like icons that failed to
   load and a control that failed to render.

   Listed explicitly rather than applied to every button in the storefront: the
   text buttons want their padding, and a blanket reset would flatten those. */
.gms-wish,
.gms-cmp,
.gms-card-qty__btn,
.gms-drawer__close,
.gms-rail__arrow,
/* The side cart's quantity stepper. It set a width and a height and no
   padding, so the theme's own button padding — 1rem, 2rem, 0.9375rem — was
   inherited whole: 64px-wide buttons in a 33px pill, and more space above the
   glyph than below it, which is what tilted the minus and plus off centre.
   (No braces in this note: a block scanner reads them as the end of a rule.) */
.gms-qty button {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  min-width: 0;
  min-height: 0;
  flex: none;
  letter-spacing: normal;
  text-transform: none;
}

/* Own the type scale.
   Block themes ship fluid body sizes — Twenty Twenty-Five resolves to ~18.2px
   at mobile — and anything inheriting from that renders a listing noticeably
   larger than intended. Setting an explicit base here makes the grid render the
   same on every theme, and gives the mobile step-down something to key off. */
.gms-listing {
  max-width: 1320px;
  margin: 0 auto;
  padding-inline: 16px;
  font-size: 16px;
  line-height: 1.5;
}

@media (max-width: 600px) {
  .gms-listing { font-size: 14px; padding-inline: 14px; }
}

/* ============================================================= hero ===== */

/* Structure lives here, not in the theme file. A theme should restyle
   components, never be required for them to render — putting the layout in
   theme-leafora.css left the light theme with an unstyled hero and an SVG
   arrow that expanded to fill the viewport. */

.gms-hero {
  position: relative;
  border-radius: var(--gms-r-lg);
  overflow: hidden;
  margin-bottom: 18px;
  min-height: 200px;
  display: flex;
  align-items: center;
  background: var(--gms-tint);
  border: 1px solid var(--gms-line-2);
}

.gms-hero__media { position: absolute; inset: 0; z-index: 0; }
.gms-hero__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.gms-hero__veil {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(100deg, rgba(255, 255, 255, .95) 0%, rgba(255, 255, 255, .7) 48%, rgba(255, 255, 255, .12) 100%);
}

.gms-hero__body { position: relative; z-index: 2; padding: 30px 28px; max-width: 62%; }

.gms-hero__eyebrow {
  display: inline-block;
  font-size: .6875em;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gms-accent);
  margin-bottom: 10px;
}

.gms-hero__title {
  margin: 0 0 8px;
  font-size: clamp(1.4rem, 3.4vw, 2rem);
  line-height: 1.16;
  font-weight: 650;
  letter-spacing: -.015em;
}

.gms-hero__text { margin: 0 0 18px; color: var(--gms-ink-2); font-size: .9375em; line-height: 1.5; max-width: 34ch; }

.gms-hero__cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 12px 22px;
  border-radius: var(--gms-r-pill);
  background: var(--gms-accent);
  color: var(--gms-accent-ink);
  font-size: .9375em;
  font-weight: 650;
  text-decoration: none;
  transition: transform .15s ease, opacity .15s ease;
}

.gms-hero__cta:hover { transform: none; color: var(--gms-accent-ink); opacity: .92; }

/* Without an explicit size an inline SVG inside a flex item can claim the whole
   container. Always constrain icons. */
.gms-hero__cta svg { width: 16px; height: 16px; flex: 0 0 16px; }

@media (max-width: 640px) {
  .gms-hero { min-height: 168px; }
  .gms-hero__body { padding: 20px 18px; max-width: 80%; }
}

/* =================================================== category tiles ===== */

.gms-catchips { display: flex; gap: 10px; overflow-x: auto; padding: 2px 2px 18px; scrollbar-width: none; }
.gms-catchips::-webkit-scrollbar { display: none; }

.gms-catchip {
  flex: 0 0 auto;
  width: 82px;
  padding: 12px 6px 10px;
  border-radius: 18px;
  border: 1px solid var(--gms-line);
  background: var(--gms-surface);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  text-decoration: none;
  color: var(--gms-ink-2);
  font-size: .6875em;
  font-weight: 600;
  text-align: center;
  transition: background .18s ease, border-color .18s ease, color .18s ease, transform .18s ease;
}

.gms-catchip:hover { transform: none; color: var(--gms-ink); }
.gms-catchip.is-active { border-color: var(--gms-accent); color: var(--gms-ink); }
.gms-catchip__icon { width: 26px; height: 26px; display: block; flex: 0 0 26px; }
.gms-catchip__icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.6; }
.gms-catchip.is-active .gms-catchip__icon { color: var(--gms-accent); }
.gms-catchip__label { display: block; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; width: 100%; }

/* ======================================================= care row ======= */

.gms-care { display: grid; grid-template-columns: repeat(auto-fit, minmax(74px, 1fr)); gap: 8px; margin: 16px 0; }

.gms-care__item {
  padding: 14px 8px;
  border-radius: var(--gms-r);
  background: var(--gms-tint);
  border: 1px solid var(--gms-line-2);
  text-align: center;
}

.gms-care__icon { width: 22px; height: 22px; margin: 0 auto 7px; color: var(--gms-accent); }
.gms-care__icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.6; }
.gms-care__label { font-size: .6875em; font-weight: 650; margin-bottom: 2px; }
.gms-care__value { font-size: .625em; line-height: 1.35; color: var(--gms-ink-2); }

/* ================================================== mobile bottom nav === */

/* One source of truth for how much room the fixed bottom chrome occupies.
   Everything pinned to the bottom offsets by this rather than each guessing —
   which is how three bars ended up stacked on top of one another. Zero by
   default; the mobile nav raises it inside its own media query. */
:root { --gms-bottom-chrome: 0px; }

.gms-mobnav {
  position: fixed;
  left: 12px; right: 12px;
  bottom: calc(10px + env(safe-area-inset-bottom));
  z-index: 99980;
  display: none;
  align-items: center;
  justify-content: space-around;
  gap: 2px;
  padding: 9px 8px;
  border-radius: 26px;
  background: var(--gms-surface);
  border: 1px solid var(--gms-line);
  box-shadow: var(--gms-shadow-lg);
}

.gms-mobnav__item {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px 2px;
  border-radius: 16px;
  text-decoration: none;
  color: var(--gms-ink-3);
  font-size: .625em;
  font-weight: 600;
  position: relative;
  transition: color .16s ease, background .16s ease;
}

.gms-mobnav__item svg { width: 20px; height: 20px; flex: 0 0 20px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.gms-mobnav__item:hover { color: var(--gms-ink); }
.gms-mobnav__item.is-active { color: var(--gms-accent); }

/* `display: grid` below would otherwise beat the hidden attribute, leaving an
   empty "0" badge sitting on the nav. */
.gms-mobnav__n[hidden] { display: none; }

.gms-mobnav__n {
  position: absolute;
  top: 2px; right: 50%;
  transform: translateX(16px);
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: var(--gms-r-pill);
  background: var(--gms-accent);
  color: var(--gms-accent-ink);
  font-size: .5625em;
  font-weight: 700;
  display: grid;
  place-items: center;
}

@media (max-width: 820px) {
  .gms-mobnav { display: flex; }

  /* Only when the nav is genuinely on the page. Unconditionally, every phone
     under 820px reserved 78px for chrome that a storefront without the mobile
     nav never renders — so the product page's buy bar, the checkout bar and
     the compare tray all floated with a strip of empty page beneath them
     instead of sitting on the bottom edge. The body rule below was already
     guarded this way; the variable was not. */
  :root:has(.gms-mobnav) { --gms-bottom-chrome: 78px; }

  body:has(.gms-mobnav) { padding-bottom: calc(var(--gms-bottom-chrome) + 6px); }
}


/* ============================================================ pills ===== */

.gms-pills {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 4px 2px 14px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.gms-pills::-webkit-scrollbar { display: none; }

.gms-pill {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px 7px 8px;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r-pill);
  background: var(--gms-surface);
  color: var(--gms-ink);
  text-decoration: none;
  font-size: .875rem;
  font-weight: 550;
  white-space: nowrap;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.gms-pill:hover { border-color: var(--gms-ink-3); color: var(--gms-ink); }
.gms-pill.is-active { background: var(--gms-ink); border-color: var(--gms-ink); color: #fff; }
.gms-pill.is-active .gms-pill__dot { background: rgba(255, 255, 255, .35); }
.gms-pill.is-active em { background: rgba(255, 255, 255, .2); color: #fff; }

.gms-pill__img { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; display: block; }
.gms-pill__dot { width: 26px; height: 26px; border-radius: 50%; background: var(--gms-tint); display: block; }

.gms-pill em {
  font-style: normal;
  font-size: .6875rem;
  padding: 1px 6px;
  border-radius: var(--gms-r-pill);
  background: var(--gms-tint);
  color: var(--gms-ink-2);
}

/* ========================================================== toolbar ===== */

.gms-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 0 14px;
  flex-wrap: wrap;
}

.gms-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r-pill);
  background: var(--gms-surface);
  color: var(--gms-ink);
  font: inherit;
  font-size: .875rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--gms-shadow);
}

.gms-filter-btn:hover { border-color: var(--gms-ink-3); }
.gms-filter-btn svg { width: 17px; height: 17px; }

.gms-filter-btn__n {
  font-style: normal;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: var(--gms-r-pill);
  background: var(--gms-accent);
  color: var(--gms-accent-ink);
  font-size: .6875rem;
  font-weight: 700;
  display: grid;
  place-items: center;
}

.gms-toolbar__count { font-size: .8125rem; color: var(--gms-ink-3); }

.gms-sort { margin-left: auto; }

.gms-sort select {
  padding: 9px 34px 9px 14px;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r-pill);
  background-color: var(--gms-surface);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 55%, calc(100% - 13px) 55%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  font-size: .875rem;
  font-weight: 550;
  color: var(--gms-ink);
  cursor: pointer;
}

/* =========================================================== chips ====== */

.gms-chips { display: flex; flex-wrap: wrap; gap: 7px; padding-bottom: 16px; align-items: center; }

.gms-chip-x {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px;
  border-radius: var(--gms-r-pill);
  background: var(--gms-tint);
  color: var(--gms-ink);
  font-size: .8125rem;
  font-weight: 550;
  text-decoration: none;
}

.gms-chip-x:hover { background: rgba(20, 22, 26, .1); color: var(--gms-ink); }
.gms-chip-x span[aria-hidden] { font-size: 1.05rem; line-height: 1; opacity: .5; }

.gms-chips__clear { font-size: .8125rem; color: var(--gms-accent); text-decoration: underline; margin-left: 4px; }

/* ============================================================ grid ====== */

.gms-grid {
  display: grid;
  grid-template-columns: repeat(var(--gms-cols, 4), minmax(0, 1fr));
  gap: var(--gms-grid-gap, 20px);
  /* An optional cap keeps four cards on a very wide screen from becoming four
     very large photographs. Centred, so the row does not hug one edge. */
  justify-content: center;
}

.gms-grid > * { max-width: var(--gms-card-max, none); width: 100%; }

@media (max-width: 1180px) { .gms-grid { grid-template-columns: repeat(var(--gms-cols-tablet, 3), minmax(0, 1fr)); } }
@media (max-width: 860px)  { .gms-grid { grid-template-columns: repeat(var(--gms-cols-mobile, 2), minmax(0, 1fr)); gap: calc(var(--gms-grid-gap, 20px) * .7); } }
@media (max-width: 380px)  { .gms-grid { gap: calc(var(--gms-grid-gap, 20px) * .6); } }

.gms-card-p {
  display: flex;
  flex-direction: column;
  background: var(--gms-surface);
  border: 1px solid var(--gms-line-2);
  border-radius: var(--gms-r-lg);
  overflow: hidden;
  transition: box-shadow .18s ease, border-color .18s ease;
}

.gms-card-p:hover { box-shadow: var(--gms-shadow); border-color: var(--gms-line); }

.gms-card-p__media {
  position: relative;
  /* Reserved ratio — the single biggest CLS win on an image-heavy listing.
     Portrait by default: 4:5 is what most commerce photography ships in and it
     gives the card a taller, more considered proportion than a square. */
  aspect-ratio: var(--gms-card-ratio, 4 / 5);
  background: var(--gms-tint);
  overflow: hidden;
}

.gms-card-p__link { display: block; width: 100%; height: 100%; }

/* The class is doubled on purpose, and removing the repetition breaks the
   card.

   Page builders ship a blanket `.elementor img { height: auto }`, which is
   (0,1,1) and beats a single class. A rail dropped into an Elementor
   container therefore rendered every photograph at its natural ratio inside
   a 4:5 box — a square image in a 208x260 well, leaving a 52px band of
   background under it that reads as the picture being cut off at the bottom.
   Only on pages built with the builder, which is what made it look like a
   home page bug rather than a card bug.

   Doubling the class makes this (0,2,0), which outranks any
   `.something img` a theme can write, without resorting to !important. */
.gms-card-p__img.gms-card-p__img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: opacity .2s ease;
}

/* Every shot after the first stacks on top of it, hidden. The cycle on hover
   swaps which one is showing — see initCardShots() in frontend.js.

   Driven by a class rather than :hover alone because the run has to keep its
   place: leaving the card mid-cycle and coming back should not start from
   whichever frame the CSS animation happened to be on. */
.gms-card-p__img--hover { position: absolute; inset: 0; opacity: 0; }
.gms-card-p__img.is-shot { opacity: 1; }
.gms-card-p__media:hover .gms-card-p__img { transform: none; }

/* Progress ticks, so a shopper can see the card has more to show and how far
   through it is. Drawn from the count the server put on the element. */
.gms-card-p__shots {
  position: absolute;
  left: 50%;
  bottom: 9px;
  transform: translateX(-50%);
  display: flex;
  gap: 4px;
  padding: 4px 7px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .3);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity .2s ease;
  pointer-events: none;
}

.gms-card-p__media:hover .gms-card-p__shots { opacity: 1; }

.gms-card-p__shots i {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .45);
  transition: background .2s ease;
}

.gms-card-p__shots i.is-on { background: #fff; }

/* A phone has no hover, so the cycle never runs and the extra images are
   weight for nothing. They are still in the markup for the crawler and for a
   tablet with a mouse; the ticks simply never appear. */
@media (hover: none) {
  .gms-card-p__shots { display: none; }
}

.gms-card-p__badges {
  position: absolute;
  top: 10px; left: 10px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  align-items: flex-start;
  pointer-events: none;
  z-index: 2;
}

/* The offer flag. Bottom of the image rather than top-left, so it never fights
   the discount badges for the same corner, and full width because "Buy 2 get 1
   free" is longer than "40% OFF" and must not be truncated into nonsense. */
/* A ribbon on the photograph, not a bar welded to the title.
   
   Full-bleed and flush to the bottom edge, it butted straight into the product
   name with nothing between them — so it read as a black stripe through the
   card rather than as a label belonging to the picture. Inset and rounded, it
   sits on the image the way the discount badge does. */
.gms-card-p__offer {
  position: absolute;
  right: 8px; bottom: 8px; left: 8px;
  z-index: 2;
  border-radius: 7px;
  padding: 5px 10px;
  background: var(--gms-ink, #1a1a1a);
  color: #fff;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1.3;
  text-align: center;
  text-transform: uppercase;
  pointer-events: none;
  /* Two lines at most; a merchant who writes an essay gets it cut rather than
     having it cover the product. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.gms-card-p__offer--member {
  background: var(--gms-accent, #2563eb);
}

/* The card's own stepper, shown once the product is in the basket.
   Same footprint as the button it replaces, so a grid of cards does not
   reflow as things are added. */
.gms-card-qty {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 40px;
  align-items: center;
  margin-top: auto;
  border: 1.5px solid var(--gms-accent);
  border-radius: var(--gms-r);
  background: var(--gms-surface);
  overflow: hidden;
  transition: opacity .15s ease;
}

.gms-card-qty.is-busy { opacity: .55; pointer-events: none; }

/* The padding reset is load-bearing, not tidiness.

   Themes style bare <button> globally, and a shop theme styles it generously —
   the one this was found on put 24px of side padding on every button. That made
   each 40px track hold a 64px control, the row overflowed, and the box clips at
   overflow: hidden. The result was a stepper with no minus, no number and no
   plus: an empty outlined rectangle where Add to cart used to be, which reads
   as a component that failed to render.

   min-width: 0 matters for the same reason — a grid item defaults to
   min-width: auto and refuses to shrink below its content, so the track size is
   a suggestion until this says otherwise. */
.gms-card-qty__btn {
  width: 100%;
  min-width: 0;
  height: 40px;
  padding: 0;
  margin: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  font: inherit;
  font-size: 1.0625rem;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  color: var(--gms-accent);
  cursor: pointer;
}

.gms-card-qty__btn:hover { background: var(--gms-accent-soft, rgba(0, 0, 0, .04)); }

.gms-card-qty__n {
  min-width: 0;
  text-align: center;
  font-size: .875rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--gms-ink);
}

.gms-chip-b {
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--gms-r-pill);
  color: #fff;
  line-height: 1.35;
}

.gms-chip-b--sale { background: var(--gms-bad); }
.gms-chip-b--new  { background: var(--gms-ink); }
.gms-chip-b--out  { background: var(--gms-ink-2); }

.gms-wish {
  position: absolute;
  top: 9px; right: 9px;
  width: 32px; height: 32px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 2;
  box-shadow: 0 1px 3px rgba(16, 24, 40, .12);
  transition: transform .15s ease;
}

.gms-wish:hover { transform: none; }
.gms-wish svg { width: 16px; height: 16px; fill: none; stroke: var(--gms-ink); stroke-width: 1.9; }
.gms-wish.is-on svg { fill: var(--gms-bad); stroke: var(--gms-bad); }

/* Body: a deliberate rhythm rather than a stack of equally-weighted rows.
   Title and price carry the card; everything else is support and is sized down
   hard so the eye lands on the two things that decide a click. */
.gms-card-p__body { display: flex; flex-direction: column; gap: 0; padding: 10px 11px 11px; flex: 1 1 auto; }

.gms-card-p__stock {
  font-size: .6875em;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--gms-ink-3);
  margin-bottom: 3px;
}

.gms-card-p__stock.is-low { color: var(--gms-warn); }

.gms-card-p__title {
  font-size: .9375em;
  font-weight: 550;
  margin: 0 0 3px;
  line-height: 1.32;
  /* A plain block. The clamp is on the link inside it — see below for why it
     cannot live here. */
  display: block;
}

/* Two lines then an ellipsis, so a long name cannot shove the price out of
   alignment with the card beside it.

   The clamp is on the link rather than the heading, and that is load-bearing.
   -webkit-line-clamp only does anything on a box that is actually rendered as
   `-webkit-box`, and a box gets blockified out of it in two situations that
   both applied here:

     1. .gms-card-p__body is a flex column, so the heading is a flex item and
        its `-webkit-box` became `flow-root`;
     2. once the heading itself was a -webkit-box, the link inside it was a
        webkit-box *item*, and blockified for the same reason.

   So the heading is a plain block and the link carries the clamp. Left on the
   heading, a long product name was cut dead at two lines with no ellipsis —
   it simply stopped mid-word.

   Verify with: getComputedStyle($0).display — it must read "-webkit-box". */
.gms-card-p__title a {
  color: inherit;
  text-decoration: none;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.gms-card-p__title a:hover { text-decoration: underline; }

.gms-card-p__rating { display: flex; align-items: center; gap: 5px; font-size: .75em; margin-bottom: 4px; }

.gms-stars {
  background: linear-gradient(90deg, #f5a623 var(--gms-fill, 0%), rgba(20, 22, 26, .16) var(--gms-fill, 0%));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  letter-spacing: 1px;

  /* Shrink-wrapped, and this is load-bearing. The fill is a gradient colour
     stop in percent, and percentages resolve against the element box — but
     background-clip: text paints it onto glyphs that occupy only as much of
     that box as five characters need. Let the box stretch and the stop lands
     past the last star, so every rating paints as five solid stars: a 2-star
     review in a 221px-wide list item put its 40% stop at 88px when the glyphs
     ended at 74px. How wrong it looked depended on the container width, which
     is why some ratings happened to render correctly and most did not. */
  width: max-content;
  max-width: 100%;
}

.gms-card-p__reviews { color: var(--gms-ink-3); }

/* The price is the loudest thing on the card after the photo. Price, strike,
   discount and saving all wrap within this one row rather than stacking. */
.gms-card-p__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 6px;
  font-size: 1.0625em;
  font-weight: 700;
  letter-spacing: -.015em;
  margin-bottom: 5px;
}

.gms-card-p__price del { opacity: .42; font-size: .8em; font-weight: 400; margin-left: 0; }
.gms-card-p__now { white-space: nowrap; }

/* The second line: discount and saving, one row, never wrapping apart. */
.gms-card-p__off {
  font-size: .6875em;
  font-weight: 600;
  color: var(--gms-good);
  margin-bottom: 6px;
  line-height: 1.3;
}

/* Swatches on the left, delivery on the right, one line total. */
.gms-card-p__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 0;
  margin-bottom: 7px;
}

.gms-card-p__meta:empty { display: none; }
.gms-card-p__meta .gms-swatches { margin-bottom: 0; flex: 0 0 auto; }

/* Left, with everything else.
   
   It was right-aligned so it could share a line with the swatches, and on the
   many cards that have no swatches it ended up alone against the right edge
   while the title, the price and the saving all ran from the left. One stray
   right-aligned line is what makes a card look thrown together. */
.gms-card-p__delivery {
  font-size: .6875em;
  line-height: 1.35;
  margin-bottom: 0;
  text-align: left;
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Where there are swatches to share the line with, the delivery still goes to
   the right of them — but it is the swatches pushing it, not the card edge. */
.gms-card-p__meta:has(.gms-swatches) .gms-card-p__delivery { text-align: right; }

.gms-card-p__delivery:empty { display: none; }
.gms-card-p__delivery .ok  { color: var(--gms-good); }
.gms-card-p__delivery .bad { color: var(--gms-bad); }

.gms-swatches { display: flex; align-items: center; gap: 5px; margin-bottom: 0; }

.gms-swatch {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--gms-swatch, #ccc);
  border: 1px solid var(--gms-line);
  display: inline-block;
}

.gms-swatch__more { font-size: .6875rem; color: var(--gms-ink-3); }

/* Fallbacks on every token this paints with.
   
   An unset custom property does not fall back to anything — it invalidates the
   whole declaration. So a .gms-btn-p rendered outside a container that declares
   the palette lost its background and its radius while keeping `color: #fff`,
   and came out as white text on nothing: a button that is present, focusable,
   clickable and invisible. It has happened on the product card, in the checkout
   dialog, and on the membership page, where it read as "there is no way to buy
   this".
   
   Scoping each new surface is the fix; these fallbacks are the safety net for
   the next surface somebody forgets. */
.gms-btn-p {
  display: block;
  width: 100%;
  margin-top: auto;
  padding: 11px 14px;
  border: 1px solid var(--gms-ink, #14161a);
  border-radius: var(--gms-r-pill, 999px);
  background: var(--gms-ink, #14161a);
  color: var(--gms-btn-p-ink, #fff);
  font: inherit;
  font-size: .8125em;
  font-weight: 650;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: opacity .15s ease, background .15s ease;
}

/* The text colour, restated at a weight the theme cannot beat.

   Measured on Zurix: the theme's link colour reaches this button at a
   specificity a single class cannot match. `.gms-btn-p` gave `#111` on a
   `#14161a` background — a luminance difference of 5, which is a black button
   with black writing on it. Two classes still lost; three wins.

   It is a token rather than `#fff` because a storefront theme is allowed to
   disagree: leafora's CTA is a pale sage gradient and wants dark text. A
   custom property inherited from `body` settles that without another round of
   specificity, which is the only reason this does not have to be `!important`.

   The variants below are tripled purely to stay above this rule. */
.gms-btn-p.gms-btn-p.gms-btn-p { color: var(--gms-btn-p-ink, #fff); }
.gms-btn-p.gms-btn-p.gms-btn-p:hover,
.gms-btn-p.gms-btn-p.gms-btn-p:focus-visible { color: var(--gms-btn-p-ink, #fff); }
.gms-btn-p--muted.gms-btn-p--muted.gms-btn-p--muted { color: var(--gms-btn-p-muted-ink, var(--gms-ink-2)); }
.gms-btn-p--ghost.gms-btn-p--ghost.gms-btn-p--ghost { color: var(--gms-btn-p-ghost-ink, var(--gms-ink-2, #57524a)); }
.gms-btn-p--ghost.gms-btn-p--ghost.gms-btn-p--ghost:hover,
.gms-btn-p--ghost.gms-btn-p--ghost.gms-btn-p--ghost:focus-visible { color: var(--gms-ink, #23201b); }

/* `display: block` above beats the user-agent `[hidden] { display: none }`,
   so swapping the button for the card's stepper left both on the card. */
.gms-btn-p[hidden] { display: none; }

/* Every property the theme's hover touches, restated.

   Shop themes style `body button:hover` and set background, colour and border
   together — the one this runs on paints its secondary-button blue. Setting
   only `color` here left the other two to the theme, so Add to cart and Buy now
   both turned blue on hover regardless of the shop's own accent. Specificity
   was never the problem; the plugin simply was not saying anything about the
   properties that changed. */
.gms-btn-p:hover,
.gms-btn-p:focus-visible {
  opacity: .88;
  background: var(--gms-ink);
  border-color: var(--gms-ink);
  color: #fff;
}
.gms-btn-p--muted { background: transparent; color: var(--gms-ink-2); border-color: var(--gms-line); }
.gms-btn-p--inline { display: inline-block; width: auto; padding: 10px 22px; }
.gms-btn-p.is-busy { opacity: .55; cursor: wait; }
.gms-btn-p.is-done { background: var(--gms-good); border-color: var(--gms-good); }

/* ==================================================== empty + pager ===== */

.gms-empty-state { text-align: center; padding: 64px 20px; }
.gms-empty-state__icon { font-size: 2rem; margin-bottom: 10px; }
.gms-empty-state h3 { margin: 0 0 6px; font-size: 1.125rem; }
.gms-empty-state p { margin: 0 0 18px; color: var(--gms-ink-2); }

/* Products under the "nothing matched" message.

   The padding above it is dropped to 24px: the empty state's own 64px was sized
   for a page with nothing else on it, and stacked with a grid it left the
   suggestions floating a long way down. */
.gms-empty-state + .gms-empty-more { margin-top: 8px; }

.gms-empty-more { padding: 24px 0 8px; border-top: 1px solid var(--gms-line); }

.gms-empty-more__title {
  margin: 0 0 16px;
  font-size: 1.0625rem;
  font-weight: 650;
  color: var(--gms-ink);
}

.gms-empty-more__grid {
  display: grid;
  grid-template-columns: repeat(var(--gms-cols, 4), minmax(0, 1fr));
  gap: var(--gms-grid-gap, 20px);
  align-items: stretch;
}

@media (max-width: 1180px) {
  .gms-empty-more__grid { grid-template-columns: repeat(var(--gms-cols-tablet, 3), minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .gms-empty-more__grid {
    grid-template-columns: repeat(var(--gms-cols-mobile, 2), minmax(0, 1fr));
    gap: calc(var(--gms-grid-gap, 20px) * .7);
  }
}

.gms-pagination { display: flex; justify-content: center; gap: 6px; padding: 30px 0 10px; flex-wrap: wrap; }

.gms-pagination .page-numbers {
  min-width: 38px; height: 38px;
  padding: 0 12px;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r-pill);
  text-decoration: none;
  color: var(--gms-ink);
  font-size: .875rem;
  font-weight: 550;
}

.gms-pagination .page-numbers:hover { border-color: var(--gms-ink-3); }
.gms-pagination .page-numbers.current { background: var(--gms-ink); border-color: var(--gms-ink); color: #fff; }
.gms-pagination .page-numbers.dots { border-color: transparent; }

/* ========================================================== filters ===== */

.gms-filters { position: fixed; inset: 0; z-index: 999998; }
.gms-filters[hidden] { display: none; }

.gms-filters__scrim {
  position: absolute; inset: 0;
  background: rgba(10, 12, 16, .45);
  opacity: 0;
  transition: opacity .25s ease;
}

.gms-filters.is-open .gms-filters__scrim { opacity: 1; }

.gms-filters__panel {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  width: min(380px, 100%);
  background: var(--gms-surface);
  color: var(--gms-ink);
  display: flex;
  flex-direction: column;
  transform: translateX(-100%);
  transition: transform .28s cubic-bezier(.22, .61, .36, 1);
  box-shadow: var(--gms-shadow-lg);
  padding-bottom: env(safe-area-inset-bottom);
}

.gms-filters.is-open .gms-filters__panel { transform: translateX(0); }

.gms-filters__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid var(--gms-line);
}

.gms-filters__head h2 { margin: 0; font-size: 1.05rem; font-weight: 650; }

.gms-filters__close {
  border: 0; background: none; font-size: 26px; line-height: 1;
  cursor: pointer; padding: 0 4px; color: inherit; opacity: .5;
}

.gms-filters__close:hover { opacity: 1; }

.gms-filters__body { flex: 1 1 auto; overflow-y: auto; padding: 4px 20px 20px; }

.gms-facet { padding: 18px 0; border-bottom: 1px solid var(--gms-line-2); }
.gms-facet:last-child { border-bottom: 0; }

.gms-facet__title {
  margin: 0 0 12px;
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gms-ink-2);
}

.gms-facet__opts { display: flex; flex-direction: column; gap: 9px; }
.gms-facet__opts--row { flex-direction: row; flex-wrap: wrap; gap: 7px; }
.gms-facet__opts--swatch { flex-direction: row; flex-wrap: wrap; gap: 9px; }

.gms-fchip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r-pill);
  font-size: .8125rem;
  font-weight: 550;
  color: var(--gms-ink);
  text-decoration: none;
  transition: border-color .15s ease, background .15s ease;
}

/* Selected states take the shop's own colour.

   Every "on" state in this panel was --gms-ink, which is near-black, so a
   filled-in filter panel read as a column of black boxes and gave no sense of
   what was active at a glance. The accent is already a setting the merchant
   picks, and it is the one thing on the page that means "this is yours" — so
   selection uses it, and the panel colours itself on any site without a line
   of per-site CSS. */
.gms-fchip:hover { border-color: var(--gms-accent); color: var(--gms-accent); }

.gms-fchip.is-on {
  background: var(--gms-accent);
  border-color: var(--gms-accent);
  color: var(--gms-accent-ink, #fff);
}
.gms-fchip em { font-style: normal; font-size: .6875rem; opacity: .55; }

.gms-fswatch {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--gms-swatch, #ccc);
  border: 2px solid transparent;
  box-shadow: 0 0 0 1px var(--gms-line);
  display: block;
  transition: transform .15s ease;
}

.gms-fswatch:hover { transform: none; }
.gms-fswatch.is-on { border-color: var(--gms-surface); box-shadow: 0 0 0 2px var(--gms-accent); }

.gms-radio, .gms-check { display: flex; align-items: center; gap: 9px; font-size: .875rem; cursor: pointer; }
.gms-radio input, .gms-check input {
  accent-color: var(--gms-accent);
  width: 16px; height: 16px; margin: 0;
  cursor: pointer;
}

/* The whole row responds, not just the 16px control. */
.gms-radio:hover, .gms-check:hover { color: var(--gms-accent); }

.gms-radio:has(input:checked),
.gms-check:has(input:checked) { color: var(--gms-ink); font-weight: 600; }

/* Gold, like every other star in the storefront. */
.gms-fstars {
  font-style: normal;
  color: #f5a623;
  letter-spacing: 1px;
}

.gms-tier { position: relative; }
.gms-tier input { position: absolute; opacity: 0; width: 0; height: 0; }

.gms-tier span {
  display: inline-block;
  padding: 7px 13px;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r-pill);
  font-size: .8125rem;
  font-weight: 600;
  cursor: pointer;
}

.gms-tier span:hover { border-color: var(--gms-accent); color: var(--gms-accent); }
.gms-tier input:checked + span {
  background: var(--gms-accent);
  border-color: var(--gms-accent);
  color: var(--gms-accent-ink, #fff);
}
.gms-tier input:focus-visible + span { outline: 2px solid var(--gms-accent); outline-offset: 2px; }

.gms-price-range { display: flex; align-items: flex-end; gap: 10px; }
.gms-price-range label { flex: 1 1 0; display: flex; flex-direction: column; gap: 5px; }
.gms-price-range label span { font-size: .75rem; color: var(--gms-ink-3); }

.gms-price-range input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--gms-line);
  border-radius: 10px;
  font: inherit;
  font-size: .875rem;
  background: var(--gms-surface);
  color: var(--gms-ink);
}

.gms-price-range input:focus {
  outline: none;
  border-color: var(--gms-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gms-accent) 18%, transparent);
}
.gms-price-range__sep { padding-bottom: 11px; color: var(--gms-ink-3); }

.gms-filters__foot {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 20px;
  border-top: 1px solid var(--gms-line);
}

.gms-filters__clear { font-size: .875rem; color: var(--gms-ink-2); text-decoration: underline; }

.gms-filters__apply {
  flex: 1 1 auto;
  padding: 12px;
  border: 0;
  border-radius: var(--gms-r-pill);
  background: var(--gms-ink);
  color: #fff;
  font: inherit;
  font-size: .9375rem;
  font-weight: 650;
  cursor: pointer;
}

/* ======================================================== cart bar ====== */

.gms-cartbar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 99990;
  /* The bottom offset is part of the base rule on purpose. Setting it in the
     mobile-nav media query further up the file loses to this shorthand, which
     is how the bar ended up sitting on top of the navigation. */
  padding: 12px 16px calc(12px + var(--gms-bottom-chrome, 0px) + env(safe-area-inset-bottom));
  pointer-events: none;
  transform: translateY(120%);
  transition: none;
}

.gms-cartbar[hidden] { display: none; }
.gms-cartbar.is-visible { transform: translateY(0); }

.gms-cartbar__btn {
  pointer-events: auto;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 20px;
  border: 0;
  border-radius: var(--gms-r-pill);
  background: var(--gms-accent);
  color: var(--gms-accent-ink);
  font: inherit;
  font-size: .9375rem;
  font-weight: 650;
  cursor: pointer;
  box-shadow: var(--gms-shadow-lg);
}

/* The label colour, restated at a weight the theme cannot beat.
 *
 * The bar already computes its own readable ink: ProductGridModule emits
 * `--gms-accent-ink` from the relative luminance of whatever bar colour the
 * merchant picked, so on a dark blue bar it resolves to white. The maths was
 * never the problem — the declaration reading it was a single class, and the
 * theme's own button colour outranked it. dentivaa.com ended up with near-black
 * text on a dark blue pill: "View your cart", the item count, the total and the
 * chevron all unreadable, on the one control the whole basket depends on.
 *
 * The children are named explicitly rather than left to inherit. They are a
 * <strong> and an <em>, and a theme's typography rules reach those directly —
 * fixing only the button would leave the price dark on some sites and not
 * others, which is worse than fixing none of it because it looks deliberate. */
.gms-cartbar__btn.gms-cartbar__btn.gms-cartbar__btn,
.gms-cartbar__btn.gms-cartbar__btn.gms-cartbar__btn strong,
.gms-cartbar__btn.gms-cartbar__btn.gms-cartbar__btn em,
.gms-cartbar__btn.gms-cartbar__btn.gms-cartbar__btn span,
.gms-cartbar__btn.gms-cartbar__btn.gms-cartbar__btn svg {
  color: var(--gms-accent-ink, #fff);
}

/* Drawn with currentColor so it follows the same token rather than needing
   its own rule the next time a theme has opinions about SVG fill. */
.gms-cartbar__btn.gms-cartbar__btn.gms-cartbar__btn svg { fill: currentColor; }

.gms-cartbar__left { display: inline-flex; align-items: center; gap: 10px; }
.gms-cartbar__left svg { width: 19px; height: 19px; }

/* The count badge that used to live here is gone.
 *
 * It styled `.gms-cartbar__left em` — fine when the bar's only <em> was a
 * round count chip sitting next to the label. The thumb/label/chevron redesign
 * replaced that markup, and the only <em> left in this subtree is
 * `.gms-cartbar__items`, the "1 item" line under the title. So the badge rule
 * quietly took it over: a 22px-tall pill, background rgba(255,255,255,.24),
 * display:grid, wrapping "1 item" onto two lines inside a box one line high.
 * Measured on dentivaa: height 22px against a scrollHeight of 48 — the word
 * "item" was simply cut in half.
 *
 * Deleted rather than narrowed to `> em`. Narrowing would leave a rule with
 * nothing to match, waiting to capture the next <em> anybody adds here. */

/* ==================================================== delivery check ==== */

.gms-delivery-check {
  margin: 18px 0;
  padding: 14px 16px;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r);
  background: var(--gms-tint);
  max-width: 420px;
}

.gms-delivery-check__label { display: block; font-size: .875rem; font-weight: 600; margin-bottom: 9px; }
.gms-delivery-check__row { display: flex; gap: 8px; }

.gms-delivery-check__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 10px 13px;
  border: 1px solid var(--gms-line);
  border-radius: 10px;
  font: inherit;
  letter-spacing: .06em;
  background: var(--gms-surface);
  color: var(--gms-ink);
}

.gms-delivery-check__input:focus { outline: none; border-color: var(--gms-ink); }

.gms-delivery-check__btn {
  flex: 0 0 auto;
  padding: 10px 20px;
  border: 0;
  border-radius: 10px;
  background: var(--gms-ink);
  color: #fff;
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}

.gms-delivery-check__btn[disabled] { opacity: .5; cursor: wait; }

.gms-delivery-check__result { margin-top: 10px; font-size: .875rem; line-height: 1.5; }
.gms-delivery-check__result:empty { display: none; }
.gms-delivery-check__result.is-loading { opacity: .6; }
.gms-delivery-check__result.is-good  { color: var(--gms-good); }
.gms-delivery-check__result.is-bad   { color: var(--gms-bad); }
.gms-delivery-check__result.is-error { color: var(--gms-warn); }
.gms-delivery-check__meta { display: block; margin-top: 3px; font-size: .8125rem; opacity: .7; }

/* ==================================================== price display ===== */

.gms-price { display: inline-flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.gms-price__now { font-weight: 700; font-size: 1.05em; }
.gms-price__mrp { text-decoration: line-through; opacity: .45; font-size: .875em; font-weight: 400; }
.gms-price__off { font-size: .8125em; font-weight: 700; color: var(--gms-good); text-transform: uppercase; }
.gms-price__save { display: block; margin-top: 3px; font-size: .8125em; color: var(--gms-good); font-weight: 550; }
.gms-price del, .gms-price ins { text-decoration: none; background: none; }

.gms-badge--sale {
  position: absolute; top: 10px; left: 10px; z-index: 4;
  background: var(--gms-bad); color: #fff;
  font-size: .75em; font-weight: 700; letter-spacing: .03em;
  padding: 4px 9px; border-radius: var(--gms-r-pill); line-height: 1.3;
  pointer-events: none;
}

.woocommerce ul.products li.product,
.woocommerce div.product div.images { position: relative; }

/* ========================================================= side cart ==== */

.gms-drawer { position: fixed; inset: 0; z-index: 999999; }
.gms-drawer[hidden] { display: none; }

.gms-drawer__scrim {
  position: absolute; inset: 0;
  background: rgba(10, 12, 16, .45);
  opacity: 0;
  transition: opacity .25s ease;
}

.gms-drawer.is-open .gms-drawer__scrim { opacity: 1; }

.gms-drawer__panel {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: min(400px, 100%);
  background: var(--gms-surface);
  color: var(--gms-ink);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform .28s cubic-bezier(.22, .61, .36, 1);
  box-shadow: var(--gms-shadow-lg);
  padding-bottom: env(safe-area-inset-bottom);
}

.gms-drawer.is-open .gms-drawer__panel { transform: translateX(0); }

.gms-drawer__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid var(--gms-line);
}

.gms-drawer__title { font-size: 1.05rem; font-weight: 650; margin: 0; }

.gms-drawer__close {
  border: 0; background: none; font-size: 26px; line-height: 1;
  cursor: pointer; padding: 0 4px; color: inherit; opacity: .5;
}

.gms-drawer__close:hover { opacity: 1; }

.gms-drawer__ship { padding: 14px 20px; border-bottom: 1px solid var(--gms-line-2); font-size: .875rem; }
.gms-drawer__ship[hidden] { display: none; }
.gms-drawer__ship-msg { margin-bottom: 8px; }
.gms-drawer__ship--done .gms-drawer__ship-msg { color: var(--gms-good); font-weight: 650; }

.gms-drawer__meter { height: 6px; border-radius: var(--gms-r-pill); background: var(--gms-tint); overflow: hidden; }
.gms-drawer__meter span { display: block; height: 100%; background: var(--gms-ink); border-radius: var(--gms-r-pill); transition: width .3s ease; }
.gms-drawer__ship--done .gms-drawer__meter span { background: var(--gms-good); }

/* One scroll region containing items, upsells and the coupon box, so the
   summary and checkout button stay pinned while everything above scrolls. */
.gms-drawer__scroll { flex: 1 1 auto; overflow-y: auto; }
.gms-drawer__items { padding: 8px 20px; }

/* ---- upsell rail ---- */

.gms-reco { padding: 16px 20px 18px; border-top: 1px solid var(--gms-line-2); }
.gms-reco[hidden] { display: none; }

.gms-reco__title {
  margin: 0 0 12px;
  font-size: .6875rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--gms-ink-3);
}

.gms-reco__rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 118px;
  gap: 10px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 4px;
}

.gms-reco__rail::-webkit-scrollbar { display: none; }

.gms-reco__card { display: flex; flex-direction: column; gap: 5px; min-width: 0; }

.gms-reco__card img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 10px;
  background: var(--gms-tint);
  display: block;
}

.gms-reco__name {
  font-size: .75rem;
  line-height: 1.35;
  color: inherit;
  text-decoration: none;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.gms-reco__price { font-size: .8125rem; font-weight: 700; display: flex; gap: 5px; align-items: baseline; }
.gms-reco__price del { font-size: .75em; font-weight: 400; opacity: .45; }

.gms-reco__add {
  margin-top: auto;
  padding: 6px 10px;
  border: 1px solid var(--gms-line);
  border-radius: var(--gms-r-pill);
  background: none;
  font: inherit; font-size: .6875rem; font-weight: 650;
  color: var(--gms-ink);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.gms-reco__add:hover { border-color: var(--gms-ink); color: var(--gms-ink); }
.gms-reco__add[disabled] { opacity: .5; }

/* ---- coupon ---- */

/* Pinned to the bottom of the scrolling area. With a long basket the coupon
   box scrolled away entirely, so the one thing a customer goes looking for
   before checking out was the hardest thing to find. */
/* First thing in the drawer's footer.
   
   It used to live in the scrolling region and pin itself there with
   position:sticky and a lifted shadow — furniture for floating over a list.
   Now that it sits in the footer, above the totals and the checkout button,
   none of that applies: it is not floating over anything, and a shadow
   pointing upwards inside a static panel just looks like a seam. */
.gms-coupon {
  margin: -4px -20px 12px;
  padding: 0 20px 12px;
  border-bottom: 1px solid var(--gms-line-2);
}

.gms-coupon__toggle {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 0; border: 0; background: none;
  font: inherit; font-size: .875rem; font-weight: 600;
  color: var(--gms-ink); cursor: pointer;
}

.gms-coupon__toggle svg { width: 17px; height: 17px; color: var(--gms-accent); }
.gms-coupon__toggle em { margin-left: auto; font-style: normal; font-size: 1.1rem; color: var(--gms-ink-3); transition: transform .18s ease; }
.gms-coupon__toggle.is-open em { transform: rotate(45deg); }

.gms-coupon__form { display: flex; gap: 8px; margin-top: 12px; }
.gms-coupon__form[hidden] { display: none; }

.gms-coupon__input {
  flex: 1 1 auto; min-width: 0;
  padding: 10px 13px;
  border: 1px solid var(--gms-line);
  border-radius: 10px;
  font: inherit; font-size: .875rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  background: var(--gms-surface);
  color: var(--gms-ink);
}

.gms-coupon__input:focus { outline: none; border-color: var(--gms-accent); }

.gms-coupon__apply {
  flex: 0 0 auto;
  padding: 10px 18px;
  border: 0; border-radius: 10px;
  background: var(--gms-ink); color: #fff;
  font: inherit; font-size: .875rem; font-weight: 650;
  cursor: pointer;
}

.gms-coupon__apply[disabled] { opacity: .5; }
.gms-coupon__error { margin: 8px 0 0; font-size: .75rem; color: var(--gms-bad); }
.gms-coupon__error:empty { display: none; }

.gms-coupon__applied { display: flex; flex-direction: column; gap: 7px; margin-top: 10px; }
.gms-coupon__applied:empty { display: none; }

.gms-coupon__chip {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 12px;
  border: 1px dashed var(--gms-good);
  border-radius: 10px;
  background: color-mix(in srgb, var(--gms-good) 7%, transparent);
  font-size: .8125rem;
}

.gms-coupon__code { font-weight: 700; letter-spacing: .03em; color: var(--gms-good); }
.gms-coupon__amt { margin-left: auto; font-weight: 650; color: var(--gms-good); }
.gms-coupon__x { border: 0; background: none; font-size: 1.05rem; line-height: 1; color: var(--gms-ink-3); cursor: pointer; padding: 0 2px; }
.gms-coupon__x:hover { color: var(--gms-bad); }

/* ---- summary ---- */

.gms-drawer__savings {
  margin-bottom: 10px;
  padding: 9px 12px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--gms-good) 9%, transparent);
  color: var(--gms-good);
  font-size: .8125rem;
  font-weight: 650;
  text-align: center;
}

.gms-drawer__savings[hidden] { display: none; }
.gms-drawer__summary { margin-bottom: 4px; }
.gms-drawer__summary:empty { display: none; }

.gms-drawer__row.is-good span:last-child { color: var(--gms-good); font-weight: 650; }
.gms-drawer__row.is-muted span:last-child { color: var(--gms-ink-3); }

.gms-drawer__row--total {
  padding-top: 10px;
  margin-top: 4px;
  border-top: 1px solid var(--gms-line);
  font-size: 1.0625rem;
}

.gms-drawer__row--total strong { font-weight: 700; }
.gms-drawer__loading, .gms-drawer__empty { padding: 40px 0; text-align: center; color: var(--gms-ink-3); }

/* Picture, description, money — the money in a column of its own so the
   prices line up down the list and every row is the same height. */
.gms-ci {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) auto;
  /* Centred, not top-aligned. With the tile now taller than the two lines of
     text beside it, `start` left the name floating against the top edge. */
  align-items: center;
  gap: 14px;
  padding: 16px 0;
  border-bottom: 1px solid var(--gms-line-2);
}

.gms-ci:last-child { border-bottom: 0; }

/* A square tile, stated at two classes and pinned three ways.
 *
 * The declared 64x80 was not what rendered: measured on dentivaa the image came
 * out 64 wide by 42.66 tall, because the theme supplies a height for images
 * that our single class did not outrank. Every row was a different height and
 * the basket looked ragged.
 *
 * width + height + aspect-ratio together, so it survives a theme that sets any
 * one of them. Square rather than the old 4:5 portrait: a cart thumbnail is
 * read as an identifier, not as product photography, and a square crops
 * sensibly whatever shape the merchant uploaded. */
.gms-ci__img.gms-ci__img {
  width: 72px;
  height: 72px;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 14px;
  background: var(--gms-tint);
  /* A pale product shot on a white drawer otherwise has no edge at all. */
  border: 1px solid var(--gms-line-2);
}
.gms-ci__body { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 7px; align-self: center; }

/* Clamped: a long product name used to push the stepper down and leave the
   rows misaligned with each other. Two lines is enough to identify something
   you have already chosen. */
.gms-ci__name {
  font-size: .9375rem; font-weight: 650; line-height: 1.3;
  text-decoration: none; color: inherit;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.gms-ci__meta { font-size: .75rem; color: var(--gms-ink-3); }

/* Right-aligned and top-aligned with the name, so the eye reads name-to-price
   straight across. */
.gms-ci__side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  text-align: right;
  align-self: center;
}

.gms-qty { display: inline-flex; align-items: center; border: 1px solid var(--gms-line); border-radius: var(--gms-r-pill); overflow: hidden; }
/* Grid, so the glyph is centred by the box rather than by its own line-height
   — a minus sign and a plus sign have different optical centres, and leaning on
   line-height leaves one of them looking low whatever number you pick. */
.gms-qty button {
  display: grid;
  place-items: center;
  /* 30px so it is still a usable target on a phone. */
  width: 30px;
  height: 30px;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 16px;
  font-weight: 500;
  line-height: 1;
  color: inherit;
}
.gms-qty button:hover { background: var(--gms-tint); }
.gms-qty button[disabled] { opacity: .3; cursor: not-allowed; }
.gms-qty__n { min-width: 26px; text-align: center; font-size: .8125rem; font-variant-numeric: tabular-nums; }

.gms-ci__price { font-size: .9375rem; font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Underlined body text next to a price read as a mistake rather than a
   control — it looked like part of the amount had been struck through. A
   small upper-case label is unmistakably a button and stays clearly
   secondary to Checkout, which is the action this panel is actually for. */
.gms-ci__remove {
  border: 0; background: none; padding: 0; cursor: pointer;
  font-size: .6875rem; font-weight: 600; letter-spacing: .02em;
  text-transform: uppercase; text-decoration: none;
  color: var(--gms-ink-3); opacity: .85;
  transition: color .15s ease, opacity .15s ease;
}
.gms-ci__remove:hover,
.gms-ci__remove:focus-visible { color: var(--gms-bad, #8a2c2c); opacity: 1; }

@media (prefers-reduced-motion: reduce) { .gms-ci__remove { transition: none; } }

/* The shadow, not just the rule, is what makes this read as pinned rather
   than as the end of the list — it matters most on a nearly empty basket,
   where there is a lot of white between the last item and the total. */
.gms-drawer__foot {
  padding: 16px 20px;
  border-top: 1px solid var(--gms-line);
  box-shadow: 0 -6px 18px rgba(20, 22, 26, .05);
}
.gms-drawer__foot[hidden] { display: none; }
.gms-drawer__row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 7px; font-size: .875rem; color: var(--gms-ink-2); }

.gms-drawer__checkout {
  display: block; padding: 14px; border-radius: var(--gms-r-pill);
  background: var(--gms-ink); color: #fff; text-align: center;
  font-weight: 650; text-decoration: none;
}

.gms-drawer__checkout:hover { opacity: .88; color: #fff; }

.gms-drawer__continue {
  display: block; width: 100%; margin-top: 8px; padding: 9px;
  border: 0; background: none; font: inherit; font-size: .875rem;
  color: var(--gms-ink-3); cursor: pointer;
}

.gms-drawer__continue:hover { color: var(--gms-ink); }
.gms-drawer.is-busy .gms-drawer__items { opacity: .5; pointer-events: none; }

body.gms-drawer-open,
body.gms-filters-open { overflow: hidden; }

/* ========================================================= responsive === */

@media (max-width: 600px) {
  .gms-delivery-check { max-width: none; }
  .gms-drawer__panel, .gms-filters__panel { width: 100%; }
  .gms-toolbar__count { display: none; }

  /* At two-up on a 375px screen each card is ~165px wide. Chrome that reads as
     comfortable at 300px reads as oversized here, so the whole card steps down
     rather than only the font. */
  .gms-card-p { border-radius: 16px; }
  .gms-card-p__body { padding: 10px 11px 12px; }
  .gms-btn-p { padding: 9px 10px; }
  .gms-wish { width: 28px; height: 28px; top: 7px; right: 7px; }
  .gms-wish svg { width: 14px; height: 14px; }
  .gms-chip-b { font-size: .625rem; padding: 3px 7px; }
  .gms-card-p__badges { top: 7px; left: 7px; gap: 4px; }
  .gms-pill { padding: 6px 12px 6px 7px; font-size: .8125rem; }
  .gms-pill__img, .gms-pill__dot { width: 22px; height: 22px; }
  .gms-filter-btn, .gms-sort select { padding: 8px 14px; font-size: .8125rem; }
  .gms-sort select { padding-right: 30px; }
  .gms-hero__body { padding: 20px 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .gms-card-p,
  .gms-card-p__img,
  .gms-drawer__panel,
  .gms-filters__panel,
  .gms-drawer__scrim,
  .gms-filters__scrim,
  .gms-cartbar { transition: none; }
}

/* ============================================================= toast ==== */

.gms-toast {
  position: fixed;
  left: 50%; bottom: 90px;
  z-index: 999992;
  display: flex; align-items: center; gap: 11px;
  padding: 12px 14px 12px 16px;
  border-radius: var(--gms-r-pill, 999px);
  background: #14161a;
  color: #fff;
  font-size: .875rem;
  font-weight: 600;
  box-shadow: 0 12px 32px rgba(16, 24, 40, .3);
  transform: translate(-50%, 20px);
  opacity: 0;
  transition: none;
}

.gms-toast.is-in { transform: translate(-50%, 0); opacity: 1; }
.gms-toast__tick { color: #6ee7a8; font-size: 1rem; }

.gms-toast__btn {
  border: 0; border-radius: var(--gms-r-pill, 999px);
  padding: 6px 14px;
  background: rgba(255,255,255,.16); color: #fff;
  font: inherit; font-size: .8125rem; font-weight: 650; cursor: pointer;
}

.gms-toast__btn:hover { background: rgba(255,255,255,.26); }

/* ============================================================= share ==== */

.gms-share { display: flex; align-items: center; gap: 8px; margin: 16px 0; flex-wrap: wrap; }
.gms-share__label { font-size: .8125rem; font-weight: 600; color: var(--gms-ink-3, #6b7280); margin-right: 2px; }

.gms-share__btn {
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border: 1px solid var(--gms-line, rgba(20,22,26,.12));
  border-radius: 50%;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: border-color .15s ease, transform .15s ease;
}

.gms-share__btn:hover { border-color: currentColor; color: inherit; }
.gms-share__btn svg { width: 17px; height: 17px; }
.gms-share__btn.is-copied { border-color: var(--gms-good, #067647); color: var(--gms-good, #067647); }

/* Cart bar variant */
.gms-cartbar--bottom-right .gms-cartbar__btn { max-width: 320px; margin: 0 0 0 auto; }

/* Apply-mode affordance */
.gms-filters__apply.is-dirty { animation: none; }
@keyframes gms-pulse { 0%,100% { opacity: 1; } 50% { opacity: .82; } }
@media (prefers-reduced-motion: reduce) { .gms-filters__apply.is-dirty { animation: none; } .gms-toast { transition: none; } }

/* ======================================================== deliver to ==== */

.gms-deliverto { padding: 13px 20px; border-bottom: 1px solid var(--gms-line-2); }
.gms-deliverto[hidden] { display: none; }

.gms-deliverto__row { display: flex; align-items: center; gap: 10px; }
.gms-deliverto__pin { width: 17px; height: 17px; flex: 0 0 17px; color: var(--gms-accent); }
.gms-deliverto__body { flex: 1 1 auto; min-width: 0; }

.gms-deliverto__label {
  display: block;
  font-size: .625rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--gms-ink-3);
}

.gms-deliverto__value {
  display: block;
  font-size: .8125rem; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.gms-deliverto__change {
  flex: 0 0 auto;
  border: 0; background: none; padding: 0;
  font: inherit; font-size: .75rem; font-weight: 700;
  color: var(--gms-accent); cursor: pointer; text-decoration: underline;
}

/* Capped and scrollable, for the same reason as the checkout list: sixteen
   saved addresses filled the whole drawer and buried the basket underneath. */
.gms-deliverto__list {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-top: 11px;
  max-height: 232px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 2px;
  margin-inline: -2px;
}
.gms-deliverto__list[hidden] { display: none; }

.gms-deliverto__panel[hidden] { display: none; }

/* Sits under the scrolling list, always reachable. */
.gms-deliverto__addnew {
  display: block;
  margin-top: 7px;
  padding: 9px 11px;
  border: 1px dashed var(--gms-line);
  border-radius: 10px;
  font-size: .75rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  color: var(--gms-accent);
}

.gms-deliverto__addnew:hover { border-color: var(--gms-accent); border-style: solid; }

/* Names its own text colour, because it is a <button>.
   
   A commerce theme styles `body button` for its own solid dark buttons, which
   means white text — and this one is a white card. We set its background and
   its border and never its colour, so the theme supplied one and it cascaded
   into everything inside that did not override it: the customer's own name
   rendered white on a pale blue card at 1.07:1, while the address line beneath
   it stayed readable because that one sets its own grey. Invisible name,
   visible address, no rule anywhere naming the colour. */
.gms-deliverto__opt {
  display: block; width: 100%; text-align: left;
  padding: 10px 12px;
  border: 1px solid var(--gms-line);
  border-radius: 10px;
  background: var(--gms-surface);
  color: var(--gms-ink, #14161a);
  font: inherit; cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}

.gms-deliverto__opt.is-on,
.gms-deliverto__opt:hover { color: var(--gms-ink, #14161a); }

.gms-deliverto__opt:hover { border-color: var(--gms-accent); }
.gms-deliverto__opt.is-on { border-color: var(--gms-accent); background: color-mix(in srgb, var(--gms-accent) 5%, transparent); }

.gms-deliverto__opt-top { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
.gms-deliverto__opt-top strong { font-size: .8125rem; }
.gms-deliverto__opt-top em {
  font-style: normal; font-size: .5625rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  padding: 1px 6px; border-radius: 999px;
  background: var(--gms-tint); color: var(--gms-ink-3);
}
.gms-deliverto__opt-lines { display: block; font-size: .6875rem; color: var(--gms-ink-2); line-height: 1.45; }

/* The "add one more to unlock" row in the cart summary. Deliberately not styled
   as a saving: nothing has been saved yet, and dressing an invitation up as a
   discount is the kind of thing that stops being believed. */
.gms-co-row.is-nudge,
.gms-sum__row.is-nudge,
[class*="row"].is-nudge {
  color: var(--gms-ink, #1a1a1a);
  background: var(--gms-tint, #f6f6f4);
  border-radius: 8px;
  padding: 9px 11px;
  font-size: .8125rem;
  font-weight: 600;
}

/* The free item an offer gave away. Not a saving line — a saving is a number,
   this is a thing you are getting, so it is stated as one and given the accent
   rather than the quiet green the discounts use. */
[class*="row"].is-free {
  color: var(--gms-good, #059669);
  background: color-mix(in srgb, var(--gms-good, #059669) 8%, transparent);
  border-radius: 8px;
  padding: 9px 11px;
  font-size: .8125rem;
  font-weight: 700;
}

/* color-mix is recent; a flat tint keeps older browsers legible rather than
   putting bold green on whatever happens to be behind it. */
@supports not (background: color-mix(in srgb, red 8%, transparent)) {
  [class*="row"].is-free { background: #ecfdf3; }
}

/* The buttons' own row, pinned to the bottom of the card so a short title and
   a long one still line their actions up across the grid. margin-top: auto
   moved here from the buttons themselves, which is where it lived when they
   were loose in the card body. */
/* Both actions on one line, side by side.
   
   Equal columns rather than equal rows: stacked, the pair took 93px of every
   card and pushed the price and the picture up the page for no gain. Side by
   side the block is one row tall whatever state it is in — and because the
   stepper takes Add to cart's column when a product is added, nothing moves at
   all between the two states. That is what keeps a row of cards aligned. */
.gms-card-p__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
  gap: 6px;
  margin-top: auto;
}

/* A lone action — "View product" on a variable one, "Request a quote" — takes
   the whole width rather than half of it with a hole beside it. */
.gms-card-p__actions > :only-child { grid-column: 1 / -1; }

/* At two-up on a phone half a card is not enough for "Add to cart", so they
   stack there and the row is two tall for every card equally. */
@media (max-width: 560px) {
  .gms-card-p__actions { grid-template-columns: 1fr; }
}

/* And whenever the card itself is narrow, regardless of the screen.

   The media query above asks the wrong question. What decides whether two
   buttons fit is the width of the card, not the width of the window, and the
   two come apart the moment a card sits in a rail: in "You may also like" on a
   916px desktop the cards are 174px, which splits into two 82px columns. "Buy
   now" wrapped onto two lines, the row went to 66px tall, and the stepper was
   squashed beside it — on a screen far too wide for the phone rule to fire.

   A container query asks the right question. The media query stays for
   browsers without support, where it is at least right about phones. */
.gms-card-p { container-type: inline-size; }

@container (max-width: 240px) {
  .gms-card-p__actions { grid-template-columns: 1fr; }
}

/* Two actions on a card stack rather than sit side by side: at card width a
   pair of buttons in a row leaves each too narrow to read, and "Add to cart"
   wraps onto two lines. */
.gms-card-p__actions .gms-btn-p { margin-top: 0; }

/* Once the product is in the basket the stepper takes Add to cart's place —
   its row, its full width — and Buy now stays where it was underneath.
   
   It was a single line, stepper and Buy now side by side, and that was wrong
   for a reason that only shows up in a grid: the actions row is pinned to the
   bottom of the card, so a 44px row against a neighbour's 93px started 49px
   lower and the two cards read as misaligned. Reserving the missing height
   instead would have left a hole under the stepper exactly where every other
   card has a button, which looks like something failed to load.
   
   Occupying the same two rows as the state it replaces means nothing moves at
   all when a product is added, and a row of cards stays a row. The stepper is
   still one control on one line, which is the part that mattered. */
.gms-card-p__actions.is-qty .gms-card-qty {
  margin-top: 0;
  width: 100%;
}

.gms-card-p__actions.is-qty .gms-btn-p { margin-top: 0; }

/* Stands in for a picture that was never attached. Same box as the image it
   replaces, so a grid of cards does not go ragged where one product has no
   photograph. */
/* A product with no photograph yet.
   
   This used to be a diagonal line across a grey box, which is the convention
   every browser and every operating system uses for an image that failed to
   load. On a shop still adding its photography that is the wrong message
   entirely: a rail of them reads as a broken page rather than a catalogue in
   progress, and the customer's conclusion is about the shop, not the picture.
   
   A quiet tint with a small centred camera glyph says the same thing honestly.
   The glyph is an inline SVG in the background so this needs no extra markup
   and no second request. */
.gms-thumb--none {
  display: block;
  border-radius: inherit;
  background-color: var(--gms-surface-2, #f4f2ef);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 24 24' fill='none' stroke='%23b8b2a8' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2.5'/%3E%3Ccircle cx='8.5' cy='10' r='1.5'/%3E%3Cpath d='M21 16l-5-5-6 6-2-2-5 4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;

  /* Scales with the box: a 64px cart thumbnail and a full-width card
     placeholder should not both get a 40px glyph. */
  background-size: 38% auto;
}

/* Only where the placeholder carries no sizing class of its own. Applying a
   width here unconditionally would have overridden .gms-ci__img's fixed 64px,
   since both are single-class selectors and this one comes later. */
.gms-thumb--box { width: 100%; aspect-ratio: 1 / 1; }

.gms-btn-p--ghost {
  background: transparent;
  border: 1px solid currentColor;
  color: var(--gms-ink-2, #57524a);
}

/* Same reasoning as the solid button above: the theme's `body button:hover`
   supplies a background and a border colour, so the ghost button has to name
   them or it stops being a ghost the moment a pointer touches it. */
.gms-btn-p--ghost:hover,
.gms-btn-p--ghost:focus-visible {
  background: transparent;
  border-color: currentColor;
  color: var(--gms-ink, #23201b);
  opacity: 1;
}

/* The offer badge is a link when the offer has a scope worth showing. It keeps
   the badge's own colours — turning it blue and underlined would read as a
   mistake on a promotional flash. */
a.gms-card-p__offer { text-decoration: none; cursor: pointer; }
a.gms-card-p__offer:hover { filter: brightness(1.08); }
a.gms-card-p__offer:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* The ribbon paints its own text, with enough specificity to survive whatever
   it is dropped into.

   `.gms-card-p__offer` is one class, (0,1,0). `.gms-pdp a` in pdp.css is
   (0,2,0) and wins — so on a product page, where the same card is reused for
   "frequently bought together" and the related rail, the ribbon took the page's
   ink instead of white and rendered near-black text on its near-black
   background. Measured at 1.02:1. The words were there, correct, and could not
   be read; on the shop grid, outside .gms-pdp, the identical card was fine.

   A card is a component. It has to look the same wherever it is placed, which
   means it cannot rely on being the most specific thing that mentions its
   links. */
.gms-card-p a.gms-card-p__offer { color: #fff; }


/* ---- The free-item chooser ------------------------------------------------
   Shown at the top of the drawer when an offer has been earned and its reward
   has not been taken. Loud on purpose: it is the one thing on the screen the
   shopper is being given rather than sold. */

.gms-reward {
  margin: 0 20px 12px;
  padding: 12px;
  border: 1.5px dashed var(--gms-accent);
  border-radius: var(--gms-r);
  background: color-mix(in srgb, var(--gms-accent) 5%, transparent);
}

.gms-reward[hidden] { display: none; }

/* Older browsers get a flat tint rather than bold accent text on whatever
   happens to be behind it. */
@supports not (background: color-mix(in srgb, red 5%, transparent)) {
  .gms-reward { background: var(--gms-tint); }
}

.gms-reward__set + .gms-reward__set { margin-top: 12px; }

.gms-reward__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 9px;
}

.gms-reward__head strong { font-size: .8125rem; font-weight: 700; color: var(--gms-ink); }

.gms-reward__head em {
  flex: 0 0 auto;
  font-style: normal;
  font-size: .625rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gms-accent);
}

/* A rail rather than a grid: the choices are a short list to scan sideways,
   and a wrapping grid of six would push the basket off the screen. */
.gms-reward__rail {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 4px;
  scrollbar-width: thin;
}

/* Same reason as .gms-deliverto__opt above: a white card that happens to be a
   <button>, so it has to name its own text colour or the theme's button colour
   walks in. */
.gms-reward__opt {
  flex: 0 0 92px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 7px;
  border: 1px solid var(--gms-line);
  border-radius: 10px;
  background: var(--gms-surface);
  color: var(--gms-ink, #14161a);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .15s ease, opacity .15s ease;
}

.gms-reward__opt:hover { border-color: var(--gms-accent); }
.gms-reward__opt.is-busy, .gms-reward__opt:disabled { opacity: .5; cursor: wait; }

.gms-reward__img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 7px;
  background: var(--gms-tint);
}

/* Two lines, so a long name does not make one card taller than its
   neighbours and leave the rail ragged. */
.gms-reward__name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(2 * 1.3em);
  font-size: .6875rem;
  line-height: 1.3;
  color: var(--gms-ink);
}

.gms-reward__price { font-size: .6875rem; font-weight: 700; color: var(--gms-accent); }
.gms-reward__price s { margin-right: 4px; font-weight: 400; color: var(--gms-ink-3); }

/* ---- A card whose product has no photograph --------------------------------
   The markup has always carried this class and nothing ever styled it, so a
   product with no picture rendered a 1×1 transparent gif stretched over a
   314px box: a large grey void that reads as a broken page rather than as a
   missing photograph. On a catalogue that has been imported but not
   photographed — which is every catalogue on its first day — that is the whole
   shop looking broken.

   Quiet, deliberate, and obviously intentional. */
/* Flat, not striped.
   
   The glyph below was always here; the diagonal hatching behind it was the
   problem. Diagonal stripes across an image slot are what a browser draws for
   an image that failed, so a grid of products awaiting photography read as a
   grid of broken images — and the conclusion a shopper draws from that is
   about the shop, not the pictures. A quiet flat tint with the camera on it
   says "no photograph yet", which is true and is not alarming. */
.gms-card-p__media--empty {
  display: grid;
  place-items: center;
  background: var(--gms-surface-2, #f4f2ef);
}

/* The transparent gif still sits in the box for layout; it must not cover the
   pattern behind it. */
.gms-card-p__media--empty .gms-card-p__img { opacity: 0; }

.gms-card-p__media--empty::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 38px;
  height: 38px;
  transform: translate(-50%, -50%);
  opacity: .28;
  background: var(--gms-ink-2, #57524a);
  /* A photograph icon, drawn rather than loaded — a placeholder that costs a
     request is a placeholder that can itself fail. */
  -webkit-mask: var(--gms-noimg) center / contain no-repeat;
  mask: var(--gms-noimg) center / contain no-repeat;
}

:root {
  --gms-noimg: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Ccircle cx='8.5' cy='10' r='1.5'/%3E%3Cpath d='M21 15l-5-5L5 19'/%3E%3C/svg%3E");
}

/* Delivery answer, on two lines.

   The date is what the customer opened the checker for; the terms are context.
   Joined with middots they ran as one line and the date sat in the middle of
   it, which is the least findable place on the row. */
.gms-delivery-check__lead { display: block; }

.gms-delivery-check__terms {
  display: block;
  margin-top: 2px;
  color: var(--gms-ink-2);
  font-size: .8125rem;
  line-height: 1.45;
}

/* ---- A wishlist control in the theme's header ----------------------------
   Inserted beside the theme's basket by the adoption routine. It deliberately
   sets almost nothing: `currentColor` and `em` sizing mean it takes the
   header's ink and scale whatever theme it lands in, which is the only way one
   rule can look right in a header it has never seen. */

.gms-header-wish {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* The row it lands in may align its children to the top or stretch them —
     neither of which looks right next to a basket icon. */
  align-self: center;
  flex: 0 0 auto;
  color: inherit;
  text-decoration: none;
  line-height: 1;
}

.gms-header-wish svg {
  width: 1.4em;
  height: 1.4em;
  display: block;
}

.gms-header-wish:hover { opacity: .75; }

.gms-header-wish__count {
  position: absolute;
  top: -.35em;
  right: -.5em;
  min-width: 1.35em;
  height: 1.35em;
  padding: 0 .3em;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--gms-brand, #a83e05);
  color: var(--gms-brand-ink, #fff);
  font-size: .625rem;
  font-weight: 700;
  line-height: 1;
}

.gms-header-wish__count[hidden] { display: none; }

/* ---- The membership suggestion, in the cart and at the checkout ----------
   One row, and it has to earn its place: it appears only when joining saves
   more than it costs on the basket in front of the customer, so it reads as
   arithmetic rather than an advertisement. */

.gms-mempitch {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 12px;
  padding: 11px 13px;
  border: 1px solid var(--gms-good, #067647);
  border-radius: var(--gms-r, 12px);
  background: color-mix(in srgb, var(--gms-good, #067647) 5%, transparent);
}

.gms-mempitch[hidden] { display: none; }

.gms-mempitch__main { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }

.gms-mempitch__main strong {
  font-size: .875rem;
  font-weight: 700;
  color: var(--gms-ink, #14161a);
}

.gms-mempitch__main span {
  font-size: .75rem;
  line-height: 1.45;
  color: var(--gms-ink-2, #5b6270);
}

.gms-mempitch__more {
  justify-self: start;
  margin-top: 2px;
  font-size: .6875rem;
  font-weight: 600;
  color: var(--gms-ink-2, #5b6270);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.gms-mempitch__add {
  flex: 0 0 auto;
  padding: 8px 16px;
  border: 0;
  border-radius: var(--gms-r-pill, 999px);
  background: var(--gms-good, #067647);
  color: #fff;
  font: inherit;
  font-size: .8125rem;
  font-weight: 700;
  cursor: pointer;
}

.gms-mempitch__add:hover { filter: brightness(1.08); color: #fff; }

@media (max-width: 420px) {
  .gms-mempitch { flex-wrap: wrap; }
  .gms-mempitch__add { width: 100%; }
}

/* ---- The theme's search, pointed at this catalogue -----------------------
   A panel rather than a redesigned header: the theme's search control keeps
   its place and its look, and this is what opens when it is pressed. Its own
   token block, because it is appended to <body> and so sits outside every
   other scope — the same trap that made the checkout dialog's button
   invisible. */

.gms-hsearch {
  --gms-ink: #14161a; --gms-ink-2: #5b6270; --gms-ink-3: #6b7280;
  --gms-line: rgba(20,22,26,.12); --gms-line-2: rgba(20,22,26,.07);
  --gms-surface: #fff; --gms-tint: #f6f7f9;
  --gms-accent: var(--gms-brand, #2563eb);
  --gms-r: 12px; --gms-r-pill: 999px;
  --gms-surface-2: #f4f2ef;

  position: fixed;
  inset: 0;
  z-index: 100001;
  display: flex;
  justify-content: center;
  padding: 8vh 16px 16px;
}

.gms-hsearch__scrim {
  position: absolute;
  inset: 0;
  background: rgba(15, 17, 21, .5);
  backdrop-filter: blur(2px);
}

.gms-hsearch__panel {
  position: relative;
  width: 100%;
  max-width: 560px;
  max-height: 76vh;
  display: flex;
  flex-direction: column;
  border-radius: var(--gms-r);
  background: var(--gms-surface);
  box-shadow: 0 24px 60px rgba(16, 24, 40, .28);
  overflow: hidden;
}

.gms-hsearch__form {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--gms-line-2);
}

.gms-hsearch__form svg { width: 18px; height: 18px; flex: 0 0 auto; color: var(--gms-ink-3); }

.gms-hsearch__form input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 1rem;
  color: var(--gms-ink);
  outline: none;
}

.gms-hsearch__x {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--gms-tint);
  color: var(--gms-ink-2);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.gms-hsearch__out { overflow-y: auto; padding: 6px; }

.gms-hsearch__hit,
.gms-hsearch__cat {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 10px;
  border-radius: 9px;
  color: var(--gms-ink);
  text-decoration: none;
  font-size: .875rem;
}

.gms-hsearch__hit:hover,
.gms-hsearch__cat:hover { background: var(--gms-tint); color: var(--gms-ink); }

.gms-hsearch__hit img,
.gms-hsearch__hit .gms-thumb--none {
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 7px;
  object-fit: cover;
  background: var(--gms-surface-2);
}

.gms-hsearch__hit-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gms-hsearch__hit-price { flex: 0 0 auto; font-weight: 700; }

.gms-hsearch__cat {
  font-weight: 650;
  color: var(--gms-ink-2);
}

.gms-hsearch__cat::before {
  content: '';
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 7px;
  background: var(--gms-tint);
}

.gms-hsearch__none { margin: 0; padding: 18px 12px; font-size: .875rem; color: var(--gms-ink-3); text-align: center; }

@media (max-width: 600px) {
  .gms-hsearch { padding: 0; }
  .gms-hsearch__panel { max-width: none; max-height: 100%; border-radius: 0; }
}

/* Page chrome, while the search panel is open.
   A scrim dims the page; it does not hide it. The offer strip's dismiss button
   is white on black and stayed perfectly legible through 50% — so a second ×
   sat a few centimetres from the panel's own, and the obvious reading was that
   the search had two close buttons. Anything that looks like a control has to
   stop looking like one while a modal owns the screen. */
body.gms-hsearch-open .gms-strip__x,
body.gms-hsearch-open .gms-bb,
body.gms-hsearch-open .gms-cartbar { visibility: hidden; }

/* ---- The account panel ---------------------------------------------------
   Slides in from the right, like the cart drawer, because it is the same kind
   of thing: a place the customer goes and comes back from, not a page. Its own
   token block — it is appended to <body>, outside every other scope. */

.gms-acctp {
  --gms-ink: #14161a; --gms-ink-2: #5b6270; --gms-ink-3: #6b7280;
  --gms-line: rgba(20,22,26,.12); --gms-line-2: rgba(20,22,26,.07);
  --gms-surface: #fff; --gms-tint: #f6f7f9;
  --gms-accent: var(--gms-brand, #2563eb);
  --gms-r: 12px; --gms-r-pill: 999px;

  position: fixed;
  inset: 0;
  z-index: 100002;
}

.gms-acctp__scrim {
  position: absolute;
  inset: 0;
  background: rgba(15, 17, 21, .45);
  backdrop-filter: blur(2px);
  animation: none;
}

.gms-acctp__panel {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: min(360px, 88vw);
  display: flex;
  flex-direction: column;
  background: var(--gms-surface);
  box-shadow: -18px 0 48px rgba(16, 24, 40, .22);
  animation: none;
}

@keyframes gms-acctp-in { from { transform: translateX(100%); } to { transform: none; } }

.gms-acctp__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--gms-line-2);
}

.gms-acctp__head h2 {
  margin: 0;
  font-size: 1rem;
  font-weight: 650;
  color: var(--gms-ink);
}

.gms-acctp__x {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  box-sizing: border-box;
  padding: 0; margin: 0; min-width: 0; min-height: 0; flex: none;
  border: 0;
  border-radius: 50%;
  background: var(--gms-tint);
  color: var(--gms-ink-2);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.gms-acctp__body { flex: 1 1 auto; overflow-y: auto; padding: 14px; }

.gms-acctp__hi {
  margin: 0 4px 12px;
  font-size: .9375rem;
  font-weight: 600;
  color: var(--gms-ink);
}

.gms-acctp__lead {
  margin: 0 4px 14px;
  font-size: .875rem;
  line-height: 1.5;
  color: var(--gms-ink-2);
}

.gms-acctp__cta {
  display: block;
  margin: 0 0 14px;
  padding: 12px;
  border-radius: var(--gms-r-pill);
  background: var(--gms-ink, #14161a);
  color: #fff;
  text-align: center;
  font-size: .9375rem;
  font-weight: 650;
  text-decoration: none;
}

.gms-acctp__cta:hover { opacity: .9; color: #fff; }

.gms-acctp__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: var(--gms-r);
  color: var(--gms-ink);
  text-decoration: none;
}

.gms-acctp__row:hover { background: var(--gms-tint); color: var(--gms-ink); }

.gms-acctp__ico {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 10px;
  background: var(--gms-tint);
  color: var(--gms-ink-2);
}

.gms-acctp__ico svg { width: 18px; height: 18px; }

.gms-acctp__txt { flex: 1 1 auto; min-width: 0; display: grid; gap: 1px; }
.gms-acctp__txt strong { font-size: .875rem; font-weight: 600; }
.gms-acctp__txt em { font-style: normal; font-size: .75rem; color: var(--gms-ink-3); }

.gms-acctp__go { flex: 0 0 auto; font-size: 20px; line-height: 1; color: var(--gms-ink-3); }

.gms-acctp__out {
  display: block;
  margin: 14px 4px 4px;
  padding-top: 14px;
  border-top: 1px solid var(--gms-line-2);
  font-size: .875rem;
  color: var(--gms-ink-2);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.gms-acctp__out:hover { color: var(--gms-ink); }

body.gms-acctp-open { overflow: hidden; }
body.gms-acctp-open .gms-strip__x { visibility: hidden; }

/* ---------------------------------------------------------------------------
   A cart with something in it, said quietly and continuously.

   The bar that confirms an add now leaves after a few seconds, because a bar
   that never leaves eats the bottom of a phone screen for the rest of the
   session and stops being read. That trades a moment's confirmation for a
   permanent one, so something has to carry the state once the bar has gone —
   this is it.

   Three beats, then stop. A badge that pulses forever is an alarm, and the
   customer has not done anything wrong.
   --------------------------------------------------------------------------- */

@keyframes gms-cart-pulse {
  0%   { transform: scale(1); }
  18%  { transform: scale(1.22); }
  38%  { transform: scale(1); }
  100% { transform: scale(1); }
}

@keyframes gms-cart-ring {
  0%   { box-shadow: 0 0 0 0 rgba(16, 122, 74, .45); }
  70%  { box-shadow: 0 0 0 9px rgba(16, 122, 74, 0); }
  100% { box-shadow: 0 0 0 0 rgba(16, 122, 74, 0); }
}

.gms-count--full {
  border-radius: 999px;
}

/* The theme's own icon, tagged by the selector the merchant configured. Only
   the scale — a ring around somebody else's markup lands on whatever padding
   they happen to have and rarely sits where you would draw it by hand. */
.gms-cart-live {
  border-radius: 999px;
}

/* Someone who has asked the operating system to stop things moving is not
   asking for a smaller version of the same thing. */
@media (prefers-reduced-motion: reduce) {
  .gms-count--full,
  .gms-cart-live {
    animation: none;
  }
}

/* ---------------------------------------------------------------------------
   The cart bar on a phone: a pill, not a bar.

   Full width, it is a wall across the bottom of every page — and because it
   stays for as long as there is something in the basket, that wall is there
   for the whole visit. Sized to its own contents it says the same thing while
   leaving the page underneath usable, which is the whole reason to keep it
   permanently rather than flashing it and taking it away.
   --------------------------------------------------------------------------- */

@media (max-width: 860px) {
  .gms-cartbar { padding-left: 12px; padding-right: 12px; }

  .gms-cartbar__btn {
    width: auto;
    max-width: min(100%, 340px);
    gap: 10px;
    padding: 7px 12px 7px 7px;
  }

  /* The total is the first thing to go. On a phone the pill is a doorway to
     the cart, not a receipt — the figure is on the other side of it, one tap
     away, and printing it here is what forced the bar full width. */
  .gms-cartbar__end strong { display: none; }
}

.gms-cartbar__left { min-width: 0; }

.gms-cartbar__thumb {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .18) center / cover no-repeat;
  display: grid;
  place-items: center;
}

.gms-cartbar__thumb svg { width: 17px; height: 17px; }

/* Once there is a photograph the icon would sit on top of it. */
.gms-cartbar__thumb.has-shot svg { display: none; }
.gms-cartbar__thumb.has-shot { background-color: #fff; }

.gms-cartbar__label {
  display: grid;
  gap: 1px;
  text-align: left;
  min-width: 0;
}

.gms-cartbar__label strong { font-size: .9375rem; font-weight: 700; line-height: 1.15; }

.gms-cartbar__items {
  font-size: .75rem;
  font-style: normal;
  font-weight: 500;
  opacity: .85;
}

.gms-cartbar__end { display: inline-flex; align-items: center; gap: 8px; }
.gms-cartbar__chev { width: 18px; height: 18px; flex: 0 0 auto; opacity: .9; }

/* ---------------------------------------------------------------------------
   The filter panel on a phone: a bottom sheet with the groups down one side.

   A left slide-in drawer is a desktop pattern reaching for a thumb at the
   bottom of the screen. A sheet comes up from where the thumb already is, and
   the two-pane split means the shopper never scrolls past one group to reach
   another — the names stay in place on the left while the options change
   beside them.

   The rail only exists below this width. On a desktop the drawer is tall
   enough to show every group in one column, and splitting it there would be
   two clicks to see what already fitted.
   --------------------------------------------------------------------------- */

/* An option hidden by the filter search must actually disappear.
   
   The chips set their own `display`, and any author display rule beats the
   browser's `[hidden] { display: none }`. So the Offers and Category chips
   stayed on screen with the hidden attribute faithfully set on every one of
   them — the search looked broken for a second, unrelated reason to the one
   in the script. Scoped to the options list so it cannot hide anything else. */
.gms-facet__opts > [hidden] { display: none; }

/* Said out loud rather than leaving an empty panel, which reads as a failure
   to load rather than an honest "nothing matches". */
.gms-filters__none {
  margin: 18px 2px;
  color: var(--gms-ink-2);
  font-size: .9375rem;
}

.gms-filters__none[hidden] { display: none; }

/* The rail is built by script on every screen, because the script has no
   business knowing the breakpoint. It is only *laid out* on a phone — so
   above that width it has to be hidden here, or it renders as a stack of
   unstyled buttons above the filters, wearing whatever the theme dresses a
   <button> in. On this store that was a column of black pills overlapping
   each other. */
.gms-filters__rail { display: none; }
.gms-filters__split { display: block; }

/* And the theme's pill radius has to come off the tabs, since they are
   buttons and every theme has an opinion about those. */
.gms-filters__tab { border-radius: 0; }

@media (max-width: 860px) {
  .gms-filters__panel {
    top: auto;
    right: 0;
    width: 100%;
    height: min(88vh, 720px);
    border-radius: 20px 20px 0 0;
    /* Slides up, not across. */
    transform: translateY(100%);
  }

  .gms-filters.is-open .gms-filters__panel { transform: translateY(0); }

  .gms-filters__head { padding: 16px 18px 10px; border-bottom: 0; }

  /* Out of the sheet and onto the dimmed page above it, which is where every
     app of this shape puts it — inside the header it competes with the title
     for the corner a thumb reaches for. */
  .gms-filters__close {
    position: absolute;
    top: -52px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px; height: 40px;
    border-radius: 50%;
    background: rgba(20, 22, 26, .82);
    color: #fff;
    opacity: 1;
    display: grid;
    place-items: center;
    font-size: 20px;
  }

  .gms-filters__body { display: flex; flex-direction: column; padding: 0; overflow: hidden; }

  .gms-filters__search { padding: 0 18px 12px; }

  .gms-filters__searchbox {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--gms-line);
    border-radius: var(--gms-r-pill);
    background: var(--gms-tint);
    font: inherit;
    font-size: .9375rem;
    color: inherit;
  }

  .gms-filters__split {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: 38% minmax(0, 1fr);
    min-height: 0;
    border-top: 1px solid var(--gms-line);
  }

  .gms-filters__rail {
    display: block;
    overflow-y: auto;
    background: var(--gms-tint);
    border-right: 1px solid var(--gms-line);
  }

  .gms-filters__tab {
    display: block;
    width: 100%;
    padding: 15px 14px;
    border: 0;
    border-left: 3px solid transparent;
    background: none;
    font: inherit;
    font-size: .9375rem;
    text-align: left;
    color: var(--gms-ink-2);
    cursor: pointer;
  }

  .gms-filters__tab.is-current {
    background: var(--gms-surface);
    border-left-color: var(--gms-accent);
    color: var(--gms-ink);
    font-weight: 650;
  }

  .gms-filters__pane { overflow-y: auto; padding: 4px 16px 16px; min-height: 0; }

  /* One group at a time — that is the whole point of the rail. */
  .gms-filters__pane .gms-facet { display: none; padding: 14px 0; border-bottom: 0; }
  .gms-filters__pane .gms-facet.is-current { display: block; }

  /* The name is already lit up in the rail beside it. */
  .gms-filters__pane .gms-facet.is-current .gms-facet__title { display: none; }

  /* Searching drops the split: a match in a group you were not looking at is
     the match most worth showing, so every group opens and the rail steps
     back until the box is cleared. */
  .gms-filters__body.is-searching .gms-filters__rail { display: none; }
  .gms-filters__body.is-searching .gms-filters__split { grid-template-columns: minmax(0, 1fr); }
  .gms-filters__body.is-searching .gms-facet { display: block; }
  .gms-filters__body.is-searching .gms-facet .gms-facet__title { display: block; }

  .gms-filters__foot { padding: 12px 16px calc(12px + env(safe-area-inset-bottom)); gap: 10px; }

  /* Two buttons of equal weight, as the reference has it: clearing is a real
     choice here, not the afterthought a text link makes it. */
  .gms-filters__clear {
    flex: 1 1 0;
    padding: 13px;
    border: 1px solid var(--gms-line);
    border-radius: var(--gms-r-pill);
    text-align: center;
    text-decoration: none;
    font-size: .9375rem;
    font-weight: 600;
  }

  .gms-filters__apply { flex: 1 1 0; padding: 13px; }
}
