/* ============================================================
   TrendiestStore — the 2026-09 skin

   THE LAST STYLESHEET ON EVERY PAGE. ts-woo.css says nothing may
   follow it and ts-fixes.css was the exception; this is the second,
   queued from ts_enqueue_last() with ts-fixes as its dependency so
   it also lands after WooCommerce's own woocommerce.css and after
   ts-account.css. Everything in here therefore wins ties on source
   order and needs no selector arms race — single classes are enough,
   and where a longer selector appears it is because WooCommerce's
   own rule is longer, not for weight's sake.

   WHAT IT IS. A re-skin, not a rebuild. The markup, the JavaScript
   and every WooCommerce hook are untouched: this file changes what
   the shop LOOKS like — the typeface and its width axis, the pink
   header and footer bands, cards without boxes, pill buttons in
   condensed capitals — and nothing about what it does. Deleting the
   one enqueue in inc/assets.php returns the shop to how it looked
   before, which is the point.

   THE ONE IDEA. Two settings of one typeface. Body copy is Archivo
   at normal width; every piece of UI a shopper reads rather than
   reads INTO — nav, buttons, headings, prices, badges, footer links
   — is Archivo at 82% width and weight 700-800, in capitals with
   open tracking. See assets/css/ts-fonts.css for why one variable
   font does both.
   ------------------------------------------------------------
    1  Display type
    2  Buttons
    3  Header band
    4  Product cards
    5  Section heads + the tab row
    6  The marketing band
    7  Footer band
    8  Product page
    9  Cart
   10  Checkout
   11  Shop grid + account
   12  Scrollbar + back to top
   13  Tablet and phone
   14  The phone header, drawer and search page (2026-09-28)
   15  The wishlist
   16  The catalogue on a phone: toolbar, sort and filter sheets
   17  Small repairs
   ============================================================ */

/* ---------- 1. Display type ---------------------------------- */
:root {
  /* the width axis, in one place. 82% is the reference's proportion:
     narrow enough to read as a display cut, wide enough that a long
     product title does not turn into a picket fence. */
  --ts-display-stretch: 82%;
  --ts-ui-track: 0.055em;
  --ts-ink: #17151a;

  /* One accent colour, everywhere. The gold --ts-star was the only
     second accent left in the theme, and it appears in three places
     that all read a token rather than a hex — the card rating row,
     the star line under the product title (a gradient, so `color`
     cannot reach it) and the review list. Re-pointing the token
     turns all three pink at once. */
  --ts-star: #e31c79;

  /* .ts-wrap's own padding-inline, so a full-bleed child can undo it */
  --ts-gutter: 20px;
}

body {
  color: var(--ts-ink);
  -webkit-font-smoothing: antialiased;
}

/*
 * ONE declaration block, applied by a long selector list rather than
 * by a utility class, because the markup is not ours to add classes
 * to — half of these elements are printed by WooCommerce.
 */
h1, h2, h3, h4, h5,
.h0, .h1, .h2, .h3, .h4, .h5,
.ts-h1, .ts-h2, .ts-h3,
.ts-head__title,
.ts-nav__link,
.ts-pcard__title,
.ts-pcard__price,
.ts-pcard__add,
.ts-pcard__badge,
.ts-pinfo__title,
.ts-btn,
.ts-foot__title,
.ts-foot__list a,
.ts-tabs__tab,
.woocommerce-Price-amount,
.button,
button.single_add_to_cart_button,
#place_order,
.checkout-button {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
}

h1, h2, h3, h4, h5,
.h0, .h1, .h2, .h3, .h4, .h5,
.ts-h1, .ts-h2, .ts-h3,
.ts-head__title {
  font-weight: 800;
  letter-spacing: -0.005em;
  text-transform: uppercase;
  line-height: 1.06;
}

/* Product titles are the merchant's own SEO strings, some of them
   ninety characters long, and several of them are marked up as
   headings — .ts-cart__name is an <h3> — so they inherit the capitals
   above unless they are named here. The product page's own <h1> is
   deliberately NOT in this list: it is the one place a title is the
   whole headline and capitals are what make it read as one. */
.ts-pcard__title,
.ts-cart__name,
.ts-packs__name,
.ts-product-title,
.woocommerce-loop-product__title,
.woocommerce-order-details .product-name,
.woocommerce-table--order-details .product-name {
  text-transform: none;
  letter-spacing: 0;
}

/* ---------- 2. Buttons --------------------------------------- */
/*
 * Every call to action in the shop is the same object: a full pill,
 * capitals, condensed, one weight. The theme had four button shapes
 * — a 10px-radius .ts-btn, a 10px .ts-pcard__add, WooCommerce's own
 * .button and #place_order — and they are unified here rather than
 * in four files.
 */
.ts-btn,
.ts-pcard__add,
.ts-packs__add,
.woocommerce .button,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
button.single_add_to_cart_button,
#place_order,
.checkout-button,
.ts-acct__cta {
  border-radius: var(--ts-r-pill);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
  line-height: 1.2;
}

.ts-btn,
.ts-pcard__add,
.ts-packs__add {
  padding-block: 12px;
}

.ts-btn--lg {
  padding: 15px 30px;
  font-size: 1.25rem;
}

.ts-btn--sm {
  padding: 9px 18px;
  font-size: 1.05rem;
}

/* WooCommerce draws its own buttons at (0,2,0) or (0,3,0); this file
   loads after woocommerce.css so a matching count is enough. */
.woocommerce .button,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
button.single_add_to_cart_button,
#place_order,
.checkout-button {
  padding: 14px 28px;
  background: var(--ts-brand);
  color: #fff;
  border: 0;
}

.woocommerce .button:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce #respond input#submit:hover,
button.single_add_to_cart_button:hover,
#place_order:hover,
.checkout-button:hover {
  background: var(--ts-brand-700);
  color: #fff;
}

/* the outline pair the reference uses for a secondary action */
.ts-btn--ghost,
.ts-btn--outline,
.ts-acct__alt {
  border: 1.5px solid currentColor;
  background: transparent;
}

/* ---------- 3. Header band ----------------------------------- */
/*
 * The bar is solid brand pink and the logo is a WHITE FILE, which is a
 * reversal: it used to be `filter: brightness(0) invert(1)` on the
 * coloured `ts-logo.webp`, on the grounds that one asset following any
 * future change to the artwork beat carrying two. What that missed is
 * what the filter actually does — it drives every opaque pixel to a
 * single value, so the red arrow above the bag and the black bag under
 * it came out as one flat silhouette with the arrow swallowed inside
 * it. `ts-logo-white.webp` is drawn white with the arrow cut away from
 * the bag, so the mark keeps its shape. The two rules that inverted it
 * are gone; header.php and footer.php name the file.
 */
/*
 * THE TOKEN, NOT THE PROPERTY. `.ts-nav { background: var(--ts-nav-bg) }`
 * is in ts-critical.css, which is INLINED AT THE END OF <head> — after
 * every <link>, so it wins every tie this file could offer at the same
 * weight. Re-pointing the token is what actually moves the bar, and
 * ts-critical carries the same value so the first paint is pink too.
 */
:root {
  --ts-nav-bg: var(--ts-brand);
  --ts-nav-bg-stuck: var(--ts-brand);
  --ts-footer-bg: var(--ts-brand);
}

.ts-nav {
  background: var(--ts-brand);
  border-bottom: 0;
  backdrop-filter: none;
}

/*
 * WHITE ONLY WHERE THE BAR IS PINK. Below 990px `.ts-nav__menu` is a
 * white drawer that drops out of the bar, and ts-mobile.css sets these
 * same links to `--ts-text` for it. This file loads after ts-mobile, so
 * an unscoped white here is white type on a white drawer.
 */
@media (min-width: 990px) {
  .ts-nav__link {
    color: #fff;
  }

  .ts-nav__link:hover,
  .ts-nav__item--active .ts-nav__link {
    color: #fff;
    opacity: 0.82;
  }

  .ts-nav__link::after {
    background: #fff;
  }
}

.ts-nav__link {
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

.ts-nav .ts-icon-btn {
  color: #fff;
}

.ts-nav .ts-icon-btn:hover {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}

/* the search pill turns into a tinted well inside the band, so it
   stops reading as a white card floating on pink */
.ts-nav .ts-search {
  background: rgba(255, 255, 255, 0.15);
  border-color: rgba(255, 255, 255, 0.4);
}

.ts-nav .ts-search:focus-within {
  background: #fff;
  border-color: #fff;
  box-shadow: none;
}

.ts-nav .ts-search input {
  color: #fff;
}

.ts-nav .ts-search:focus-within input {
  color: var(--ts-ink);
}

.ts-nav .ts-search input::placeholder {
  color: rgba(255, 255, 255, 0.75);
}

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

.ts-nav .ts-search__go {
  background: #fff;
  color: var(--ts-brand);
}

.ts-nav .ts-search__go:hover {
  background: rgba(255, 255, 255, 0.85);
  color: var(--ts-brand-700);
}

/* the cart pill inverts: white pill, pink ink */
.ts-nav .ts-cart-pill {
  background: #fff;
  color: var(--ts-brand);
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
}

.ts-nav .ts-cart-pill:hover {
  background: rgba(255, 255, 255, 0.86);
  color: var(--ts-brand-700);
}

/* THE COUNT IS NOT A BADGE. It was a filled pink bubble on the white
   pill — a second, louder colour block inside a control that is already
   the loudest thing in the tool cluster, and at 12px it read as an
   alert rather than as "how many things you have". It is the same ink
   as the word beside it now, just set apart by a hairline. */
.ts-nav .ts-cart-pill [data-ts-cart-count] {
  padding-left: 8px;
  border-left: 1px solid rgba(227, 28, 121, 0.28);
  background: none;
  color: inherit;
  font-weight: 700;
}

/* The panels that hang off the bar stay white — they are content,
   not chrome, and white-on-pink text inside a pink panel is where
   this sort of change usually goes wrong. */
.ts-mega,
.ts-acct__panel,
.ts-predictive {
  color: var(--ts-ink);
}

/* the announcement strip above it picks up the same voice */
.announcement-bar__message {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

/* ---------- 4. Product cards --------------------------------- */
/*
 * NO BOX. The card had a hairline border, a 16px radius, a hover lift
 * and a blush ground behind the photo; the reference has none of
 * those — the product sits on the page and the only edge in the grid
 * is the button. That is only legible because every thumbnail is now
 * a white square at the same scale (see the phase-2 image pass), so
 * the photos line up without a frame to line them up.
 */
.ts-pcard {
  border: 0;
  border-radius: 0;
  background: transparent;
  overflow: visible;
}

.ts-pcard:hover {
  transform: none;
  box-shadow: none;
  border-color: transparent;
}

.ts-pcard__media {
  border-radius: var(--ts-r-sm);
  background: #fff;
}

/* No padding: every thumbnail is now a white square with its own
   margin built in (the phase-2 image pass), so a second one inside
   the card just made the product smaller than the tile it sits in.

   `height: 100%` IS A TIE-BREAK AGAINST WOOCOMMERCE, NOT A REPEAT.
   ts-glow.css already sizes this image `width:100%; height:100%;
   object-fit:contain` inside the square `.ts-pcard__media` — but
   woocommerce.css ships `.woocommerce img, .woocommerce-page img {
   height: auto }` at the same (0,1,1) and loads AFTER ts-glow, so on
   every WooCommerce page (the shop, a category archive, a product's
   related row) the height went back to `auto`. A square photo is
   unchanged by that; a PORTRAIT original is laid out at its own
   aspect ratio, taller than the frame, and the frame's
   `overflow: hidden` cut the bottom of the product off. This file is
   the last stylesheet on every page, so the same specificity wins the
   tie here. */
.ts-pcard__media img {
  padding: 0;
  height: 100%;
}

.ts-pcard__body {
  align-items: flex-start;
  gap: 4px;
  padding: 12px 2px 0;
  text-align: left;
}

.ts-pcard__badge {
  top: 8px;
  left: 8px;
  padding: 4px 9px;
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

.ts-pcard__title {
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.3;
}

.ts-pcard__price {
  gap: 8px;
  padding-top: 2px;
  font-size: 1.3rem;
  font-weight: 800;
}

.ts-pcard__was {
  font-weight: 500;
}

.ts-pcard__meta {
  font-size: 0.98rem;
}

.ts-pcard__rating {
  gap: 6px;
}

.ts-pcard__add {
  margin-top: 11px;
  gap: 8px;
}

/* the gift-pack rail borrows the same card language */
.ts-packs__card {
  border-radius: var(--ts-r-sm);
}

.ts-packs__name {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
}

.ts-packs__price {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 800;
}

/* ---------- 5. Section heads + the tab row ------------------- */
.ts-head__title {
  font-size: clamp(1.9rem, 2.6vw, 2.5rem);
}

.ts-head__sub {
  font-size: 1.15rem;
}

.ts-head__link {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

/*
 * THE TAB ROW. Three panels are in the HTML and two are `hidden`;
 * the tabs are real links to ?ts-tab=… resolved on the server, so
 * with JavaScript off a click is a page load that opens the right
 * panel, and with it assets/js/ts-tabs.js swaps them in place.
 * See template-parts/sections/tabs.php.
 */
.ts-tabs__bar {
  display: flex;
  justify-content: center;
  gap: clamp(4px, 2vw, 34px);
  margin: 0 0 26px;
  padding: 0;
  border-bottom: 1px solid var(--ts-line);
  list-style: none;
}

.ts-tabs__tab {
  display: block;
  padding: 10px clamp(8px, 2vw, 22px) 12px;
  border: 0;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  background: none;
  color: var(--ts-muted);
  font-weight: 800;
  font-size: clamp(1.25rem, 2vw, 1.7rem);
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.2s var(--ts-ease), background-color 0.2s var(--ts-ease);
}

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

.ts-tabs__tab.is-active {
  color: var(--ts-brand);
  background: var(--ts-bg-3);
  border-bottom-color: var(--ts-brand);
}

.ts-tabs__panel[hidden] {
  display: none;
}

/*
 * SIX CARDS IN THE MARKUP, FIVE ON ANYTHING WIDER THAN A PHONE.
 *
 * front-page.php asks for six because the phone grid is two columns
 * (§12) and five leaves a single card alone on the third row. The
 * count is decided on the server — one HTML for one cached page — so
 * the sixth is dropped here instead, and every desktop row stays the
 * five it was.
 *
 * The cost is real and small: a card in the markup registers itself
 * with ts_seen_products() whether or not it is painted, so the sixth
 * product of each tab is excluded from the feed at the foot of the
 * page on a desktop as well. It is one product per tab and it is still
 * in /shop/ and in its category.
 */
@media (min-width: 750px) {
  .ts-tabs__panel .ts-products > .ts-pcard:nth-child(n + 6) {
    display: none;
  }
}

.ts-tabs__foot {
  margin-top: 26px;
  text-align: center;
}

.ts-tabs__all {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ts-muted);
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: var(--ts-ui-track);
  text-decoration: none;
}

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

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

/* ---------- 6. The marketing band ---------------------------- */
/*
 * The old banner carried its own headline baked into the artwork, so
 * the section was an image and a link and nothing else. This one is
 * a photograph with no words in it, so the words are real text over
 * it — which also means they are indexable, translatable and legible
 * at any width, none of which was true of the last one.
 */
.ts-promo2 {
  position: relative;
  display: block;
  border-radius: var(--ts-r-lg);
  overflow: hidden;
  background: var(--ts-bg-3);
  text-decoration: none;
  color: inherit;
}

.ts-promo2 img {
  display: block;
  width: 100%;
  height: auto;
}

/*
 * A scrim, because the photograph does not have a quiet corner. The
 * left third is a glass cup full of pink product, and three lines of
 * grey set straight onto it were unreadable — the lead ran across the
 * cup's lid at about 2:1 contrast. This is a wash in the photo's own
 * pink rather than a grey veil, so it reads as part of the picture,
 * and it stops well before the products on the right.
 */
.ts-promo2::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    98deg,
    rgba(255, 238, 245, 0.97) 0%,
    rgba(255, 238, 245, 0.94) 24%,
    rgba(255, 238, 245, 0.6) 40%,
    rgba(255, 238, 245, 0) 56%
  );
  pointer-events: none;
}

.ts-promo2__copy {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  width: min(42%, 46ch);
  padding: clamp(18px, 3vw, 46px);
}

.ts-promo2__eyebrow {
  margin: 0 0 6px;
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ts-brand-700);
}

.ts-promo2__title {
  margin: 0 0 8px;
  font-size: clamp(2rem, 3.4vw, 3.4rem);
  color: var(--ts-ink);
}

.ts-promo2__lead {
  margin: 0 0 18px;
  max-width: 34ch;
  font-size: clamp(1.15rem, 1.4vw, 1.35rem);
  color: var(--ts-text-2);
}

.ts-promo2__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 26px;
  border-radius: var(--ts-r-pill);
  background: var(--ts-brand);
  color: #fff;
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

.ts-promo2__cta {
  white-space: nowrap;
}

/* ts_icon() prints a bare <svg> with no size of its own; without this
   it inherits the button's font-size and comes out as a 40px arrow. */
.ts-promo2__cta svg {
  width: 15px;
  height: 15px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

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

/* ---------- 7. Footer band ----------------------------------- */
.ts-foot {
  background: var(--ts-brand);
  border-top: 0;
  color: #fff;
}

/* FIVE COLUMNS NOW, NOT FOUR. footer.php gained a "let's connect"
   column beside the three link lists, and the grid it inherits is
   `1.4fr repeat(3, 1fr)` — a fifth child dropped onto a second row
   under the brand block. */
.ts-foot__grid {
  grid-template-columns: 1.5fr repeat(3, minmax(0, 1fr)) 1.35fr;
}

/* the glow the blush footer needed has nothing to sit on now */
.ts-foot::before,
.ts-foot::after {
  display: none;
}

.ts-foot__brand img {
  width: clamp(140px, 16vw, 200px);
}

.ts-foot__blurb {
  color: rgba(255, 255, 255, 0.82);
  font-size: 1.15rem;
  max-width: 38ch;
}

.ts-foot__title {
  margin: 0 0 12px;
  color: #fff;
  font-weight: 800;
  font-size: 1.2rem;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

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

.ts-foot__list a {
  color: rgba(255, 255, 255, 0.92);
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  text-decoration: none;
}

.ts-foot__list a:hover {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* the connect column, in the slot the reference gives a newsletter.
   It is WhatsApp and Instagram rather than an email capture, because
   there is no list to capture onto — a signup box that posts nowhere
   is worse than no signup box. */
.ts-foot__connect h2 {
  margin: 0 0 14px;
  color: #fff;
  font-size: clamp(1.9rem, 2.4vw, 2.6rem);
  line-height: 1.05;
}

.ts-foot__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  max-width: 320px;
  padding: 14px 20px;
  margin-bottom: 10px;
  border-radius: var(--ts-r-pill);
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.2s var(--ts-ease), color 0.2s var(--ts-ease);
}

.ts-foot__cta--solid {
  background: #fff;
  color: var(--ts-brand);
}

.ts-foot__cta--solid:hover {
  background: rgba(255, 255, 255, 0.86);
}

.ts-foot__cta--outline {
  border: 1.5px solid rgba(255, 255, 255, 0.75);
  color: #fff;
}

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

.ts-foot__cta svg {
  width: 17px;
  height: 17px;
  flex: none;
}

.ts-foot__bar {
  border-top: 1px solid rgba(255, 255, 255, 0.28);
  color: rgba(255, 255, 255, 0.86);
  font-size: 1.05rem;
}

.ts-foot__bar a {
  color: #fff;
}

/* Outlined circles at rest, the way the reference draws them. ONLY the
   resting state: ts-fixes.css §11 gives each icon its own brand colour
   on hover — Instagram's gradient, TikTok black, WhatsApp green — and
   that is worth keeping, so nothing here touches :hover. */
.ts-foot__social a {
  border-color: rgba(255, 255, 255, 0.7);
  background: transparent;
  color: #fff;
}

/* ---------- 8. Product page ---------------------------------- */
/* The disclosure rows under the buy block read as UI, not as prose, so
   they take the condensed capitals every other control on the page
   has — "PRODUCT DETAILS", the way the reference sets them. */
.ts-pinfo__title {
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

.product__title,
.product__title h1 {
  font-size: clamp(2.2rem, 3.2vw, 3.2rem);
  text-transform: uppercase;
  letter-spacing: -0.005em;
}

.ts-product-reviews h2,
.ts-related h2,
.related > h2,
.up-sells > h2 {
  font-size: clamp(1.8rem, 2.4vw, 2.3rem);
}

/* the buy block's price, in the display cut like the cards' */
.product .price,
.product .price .woocommerce-Price-amount {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 800;
}

/*
 * THE THUMBNAIL RAIL STANDS UP ON A DESKTOP. The reference puts it in
 * a column to the left of the photo; the theme had it as a row under
 * it. `media-gallery` becomes a flex row and the two children are
 * re-ordered, so the MARKUP is untouched — which matters, because
 * ts-fixes.css §1 hangs a lot of scroller behaviour off this rail and
 * ts-gallery.js addresses both by data attribute.
 *
 * The horizontal scroller's own rules have to be undone one axis at a
 * time: `overflow-x: auto` on a column would clip nothing and scroll
 * nothing, and `scroll-snap-type: x` would snap on the wrong axis.
 * Below 990px the page is one column and the row is right, so none of
 * this applies there.
 */
@media (min-width: 990px) {
  /* `stretch`, NOT `flex-start`: it is what gives the rail a resolved
     height to scroll inside, so the column ends level with the photo
     instead of running 200px past the bottom of it. */
  product-info .product__media-gallery {
    display: flex;
    align-items: stretch;
    gap: 12px;
  }

  product-info .ts-gallery__stage {
    order: 2;
    flex: 1 1 auto;
    min-width: 0;
  }

  product-info .thumbnail-slider {
    order: 1;
    flex: 0 0 94px;
    min-height: 0;
    margin-top: 0;
  }

  product-info .product__media-gallery .thumbnail-list,
  .product__media-wrapper .thumbnail-list {
    flex-direction: column;
    /* `height: 100%` for the stretched case; the cap is what stops a
       product with ten photos from making the rail taller than the
       photo it belongs to. Past it the column scrolls. */
    height: 100%;
    max-height: 520px;
    overflow-x: hidden;
    overflow-y: auto;
    scroll-snap-type: y proximity;
    justify-content: flex-start;
  }

  product-info .thumbnail-list__item {
    width: 100%;
    scroll-snap-align: start;
  }
}

/* the thumbnail rail: a plain square with a pink edge when active,
   which is what the reference draws and what the theme's soft cards
   were not */
.thumbnail-list li img,
.thumbnail-list button img {
  border-radius: var(--ts-r-sm);
  background: #fff;
}

.thumbnail-list [aria-current='true'] img,
.thumbnail-list .is-active img {
  outline: 1.5px solid var(--ts-brand);
  outline-offset: -1px;
}

/* ---------- 9. Cart ------------------------------------------ */
.ts-cart h1,
.woocommerce-cart h1,
.woocommerce-cart-form h2 {
  text-transform: uppercase;
}

.cart_totals h2,
.ts-cart__summary h2 {
  font-size: 1.7rem;
}

/* ---------- 10. Checkout ------------------------------------- */
/*
 * SIMPLER, NOT DIFFERENT. Nothing about how the checkout works is
 * touched here — the field set, the delivery table, the payment
 * block and the Rs 500 gate are all where inc/woo-shop.php put them.
 * What changes is the drawing: flat grey wells instead of outlined
 * boxes, one hairline between blocks instead of panels inside
 * panels, and the summary reading as a list rather than a table.
 */
.ts-checkout__h,
.ts-checkout__h2 {
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: var(--ts-ui-track);
}

/*
 * `form.ts-checkout`, NOT `.ts-checkout`. WooCommerce draws these
 * through `.woocommerce form .form-row .input-text` — three classes
 * AND an element, (0,3,1) — so a three-class selector here loses on
 * weight however late this file loads. The element name is what
 * squares the count; see the same trap in ts-fixes.css §0, which
 * solved it by re-pointing --wc-form-* instead.
 *
 * Grey wells rather than pink outlines: a checkout is a form, and the
 * reference draws its fields as something to type into rather than as
 * seven more bordered cards on a page that already has three.
 */
.woocommerce-checkout form.ts-checkout .form-row .input-text,
.woocommerce-checkout form.ts-checkout .form-row select,
.woocommerce-checkout form.ts-checkout .form-row textarea {
  border-radius: var(--ts-r-sm);
  background: #f6f6f7;
  border: 1px solid #e4e2e6;
}

.woocommerce-checkout form.ts-checkout .form-row .input-text:focus,
.woocommerce-checkout form.ts-checkout .form-row select:focus,
.woocommerce-checkout form.ts-checkout .form-row textarea:focus {
  background: #fff;
  border-color: var(--ts-ink);
  box-shadow: 0 0 0 1px var(--ts-ink);
}

/*
 * THE DISCOUNT BOX IS ITS OWN <form> AND MISSED ALL OF THE ABOVE.
 * `form.checkout_coupon` is a sibling of `form.ts-checkout`, not a
 * descendant, so every `form.ts-checkout .form-row` rule above skips it
 * — and it came out with WooCommerce's own near-black 4px-radius input
 * sitting inside a page of grey wells. It matters more now than it did:
 * ts_checkout_coupon_position() moved this form to just above Place
 * order, where it is the last thing a shopper looks at.
 *
 * (0,4,1) BEATS WOO'S (0,3,1) — the element name is on the form here
 * for the same reason it is on the selector above.
 */
.woocommerce-checkout form.ts-checkout__coupon .form-row .input-text {
  border-radius: var(--ts-r-sm);
  background: #f6f6f7;
  border: 1px solid #e4e2e6;
}

.woocommerce-checkout form.ts-checkout__coupon .form-row .input-text:focus {
  background: #fff;
  border-color: var(--ts-ink);
  box-shadow: 0 0 0 1px var(--ts-ink);
}

/* Apply is secondary to Place order under it, so it is the outline pill
   rather than a second solid one — but a real outline, not the ghost
   button's hairline, which vanished against the tinted panel.
   `button.button[name='apply_coupon']` IS PART OF THE SELECTOR because
   ts-fixes.css §? draws that exact button at (0,3,1); a plain `button`
   here is (0,2,2) and loses however late this file loads. */
.woocommerce-checkout form.ts-checkout__coupon button.button[name='apply_coupon'] {
  border: 1px solid var(--ts-ink);
  background: transparent;
  color: var(--ts-ink);
}

.woocommerce-checkout form.ts-checkout__coupon button.button[name='apply_coupon']:hover {
  background: var(--ts-ink);
  border-color: var(--ts-ink);
  color: #fff;
}

/*
 * Select2 draws its own box over the <select> it hides, so styling the
 * select alone leaves the Province field as the one pink outline in a
 * column of grey wells. WooCommerce skips select2 on the country field
 * (one option), which is why only this one needs it.
 */
.woocommerce-checkout form.ts-checkout .select2-container .select2-selection--single {
  height: auto;
  min-height: 46px;
  padding: 6px 4px;
  border-radius: var(--ts-r-sm);
  background: #f6f6f7;
  border: 1px solid #e4e2e6;
}

.woocommerce-checkout form.ts-checkout .select2-container--open .select2-selection--single {
  background: #fff;
  border-color: var(--ts-ink);
}

.ts-checkout__summary {
  border-radius: var(--ts-r);
}

/* the toggle is the summary's whole header: a row you press, with
   the total on it, so the item list can start closed without hiding
   the number the shopper came to check */
.ts-checkout__summary-toggle {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

.ts-checkout__summary-total {
  font-weight: 800;
  font-size: 1.4rem;
  text-transform: none;
}

/*
 * THE STRIP IS NO LONGER A PHONE CONTROL. ts-fixes.css §6 keeps it
 * `display:none` and §13 turns it on under 1100px; here it is on at
 * every width, because the reference checkout collapses its item list
 * on a desktop too and the panel is more legible for it.
 *
 * Both halves are gated on `html.ts-js`. Without the script the toggle
 * cannot be worked, so it is hidden and the list simply stays open —
 * the fallback has to be the readable one.
 */
html.ts-js .ts-checkout__summary-toggle {
  display: flex;
}

html.ts-js .ts-checkout__summary #order_review_heading {
  display: none;
}

html.ts-js .ts-checkout--summary-closed .ts-checkout__summary #order_review {
  display: none;
}

.ts-checkout__summary-caret {
  transition: transform 0.25s var(--ts-ease);
}

.ts-checkout__summary-toggle[aria-expanded='false'] .ts-checkout__summary-caret {
  transform: rotate(-90deg);
}

/* the order table reads as rows of a receipt, not a bordered grid */
.woocommerce-checkout-review-order-table,
.woocommerce-checkout-review-order-table td,
.woocommerce-checkout-review-order-table th {
  border-left: 0;
  border-right: 0;
}

.woocommerce-checkout-review-order-table tfoot .order-total th,
.woocommerce-checkout-review-order-table tfoot .order-total td {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-weight: 800;
  font-size: 1.45rem;
}

#place_order {
  width: 100%;
  padding: 17px 24px;
  font-size: 1.3rem;
}

/* ---------- 11. Shop grid + account -------------------------- */
.woocommerce-products-header__title,
.ts-shop__title {
  text-transform: uppercase;
}

.ts-account__title,
.ts-auth__title,
.ts-auth h1 {
  text-transform: uppercase;
}

/* ---------- 12. Scrollbar + back to top ---------------------- */

/*
 * THE PAGE SCROLLBAR IS SET ON :root AND NOWHERE ELSE, and that is the
 * whole trick. `scrollbar-color` INHERITS, so one declaration here
 * carries the brand down to every scroller on the site that has not
 * asked for something else — and the ones that have asked still win,
 * because they set the property on themselves: the gift-pack rail and
 * the account chip row keep their `scrollbar-width: none`, and the
 * filter column keeps the quieter `--ts-line-2` thumb it was given so
 * it does not compete with the products beside it.
 *
 * Both syntaxes are here on purpose and they do not fight. Firefox and
 * Chrome 121+ read `scrollbar-color`; Safari has never supported it and
 * reads the ::-webkit-* rules instead. Chrome ignores those the moment
 * `scrollbar-color` is set on the same element, so the pair is a
 * fallback rather than a double paint — and both take the same two
 * tokens, so it does not matter which engine picks which. The colour
 * itself lives in ts-tokens.css (--ts-scroll-thumb): light pink at
 * rest, brand pink on hover, and the note there says why round that
 * way.
 *
 * `html::-webkit-scrollbar` and NOT a bare `::-webkit-scrollbar`: the
 * bare selector matches every scrollable element on the page at (0,0,0),
 * which is one point under every `.something::-webkit-scrollbar` the
 * theme already has — so it would repaint the insides of the rails that
 * deliberately hide theirs. See ts-glow.css §packs and ts-account.css.
 */
:root {
  scrollbar-color: var(--ts-scroll-thumb) var(--ts-brand-wash);
  scrollbar-width: thin;
}

html::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

html::-webkit-scrollbar-track {
  background: var(--ts-brand-wash);
}

html::-webkit-scrollbar-thumb {
  border: 2px solid transparent;
  border-radius: 999px;
  /* the border is transparent, so the thumb has to paint into its own
     padding box or the inset reads as a gap in the bar */
  background: var(--ts-scroll-thumb);
  background-clip: padding-box;
}

html::-webkit-scrollbar-thumb:hover {
  background: var(--ts-scroll-thumb-hover);
  background-clip: padding-box;
}

/*
 * Back to top.
 *
 * ONLY DRAWN WITH THE SCRIPT (`html.ts-js`), which is the opposite of
 * the call made for the cart's Update button in ts-fixes.css §5 — and
 * for the opposite reason. That button is the ONLY way a typed quantity
 * reaches WooCommerce with JavaScript off, so it has to survive; this
 * is a shortcut to a place the shopper can already reach by scrolling.
 * Without the script there is nothing to decide when it should appear,
 * so it would sit over the page from the first pixel to the last, and a
 * permanent floating button covering the corner of a product grid is
 * worse than no button.
 *
 * It is still a real `<a href="#ts-nav">` in the markup rather than a
 * <button>: middle-click and "open in new tab" do something sensible,
 * and the script only has to add smooth scrolling and focus, not the
 * destination.
 */
.ts-totop {
  position: fixed;
  right: max(18px, env(safe-area-inset-right));
  bottom: max(18px, env(safe-area-inset-bottom));
  /* under the filter sheet (60) and the drawer scrim, over everything
     that scrolls past underneath */
  z-index: 40;
  display: none;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--ts-brand);
  color: #fff;
  box-shadow: 0 6px 20px rgba(227, 28, 121, 0.34), 0 1px 3px rgba(23, 21, 26, 0.18);
  opacity: 0;
  transform: translateY(12px);
  /* VISIBILITY, NOT JUST OPACITY — the same trade ts-mobile.css §2 makes
     for the drawer, and for the same reason: an `opacity: 0` link is
     still in the tab order, so a keyboard user would land on a control
     they cannot see, halfway down a page, with no way to tell what it
     is. `visibility` takes it out; the 0s delay on the way out is what
     lets the fade finish before it disappears. */
  visibility: hidden;
  transition: opacity 0.24s var(--ts-ease), transform 0.24s var(--ts-ease),
    background 0.18s var(--ts-ease), visibility 0s linear 0.24s;
}

html.ts-js .ts-totop {
  display: grid;
}

.ts-totop.is-in {
  opacity: 1;
  transform: none;
  visibility: visible;
  transition-delay: 0s;
}

.ts-totop:hover,
.ts-totop:focus-visible {
  background: var(--ts-brand-700);
  color: #fff;
}

.ts-totop:active {
  transform: translateY(1px);
}

.ts-totop svg {
  width: 18px;
  height: 18px;
  /* the arrow is drawn as a stroke so it stays crisp at 46px and picks
     up `color` from the states above */
  stroke: currentColor;
  stroke-width: 2.2;
  fill: none;
}

/*
 * The read-progress ring around it. `--ts-progress` is written by
 * ts-theme.js from the same rAF-throttled scroll callback everything
 * else uses, so this costs no listener of its own. A conic-gradient in
 * a `mask` rather than an SVG circle: no second element, no dasharray
 * arithmetic, and it degrades to a plain button in anything that cannot
 * mask, which is the correct thing to lose.
 */
.ts-totop::before {
  position: absolute;
  content: '';
  /* outside the button, so the ring is read against the PAGE and its
     two colours have to work there. White on white is invisible, which
     is what a first pass drew: the ring is brand pink over the same
     pink at --ts-line's opacity, the pair this theme already uses for
     a filled track anywhere else. */
  inset: -6px;
  border-radius: 50%;
  background: conic-gradient(
    var(--ts-brand) calc(var(--ts-progress, 0) * 1turn),
    var(--ts-line) 0
  );
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .ts-totop {
    transform: none;
    transition: opacity 0.01ms;
  }

  .ts-totop:active {
    transform: none;
  }
}

/* ---------- 13. Tablet and phone ----------------------------- */
@media (max-width: 989px) {
  /* A 2.3:1 photograph has no room to read anything over it once the
     window is this narrow, so the copy comes out from under the image
     and sits below it — and the scrim goes with it. */
  .ts-promo2 {
    background: var(--ts-bg-2);
  }

  .ts-promo2::after {
    display: none;
  }

  .ts-promo2__copy {
    position: static;
    width: auto;
    background: var(--ts-bg-2);
  }
}

@media (max-width: 749px) {
  /* A 2.3:1 banner is 167px tall on a 390px phone, which renders the
     products in it about 40px wide. Cropping to 16:10 and holding the
     frame just left of centre keeps the cup and the first few products
     at a size somebody can actually see. */
  .ts-promo2 img {
    aspect-ratio: 16 / 10;
    object-fit: cover;
    object-position: 42% center;
  }
}

/*
 * The connect column is the first thing to run out of room: five
 * columns in 984px leaves it 185px, and "Message us on WhatsApp" needs
 * about 210. Below 1200px it drops to a full-width row under the four
 * link columns and the two buttons sit side by side instead.
 */
@media (max-width: 1199px) {
  .ts-foot__grid {
    grid-template-columns: 1.4fr repeat(3, minmax(0, 1fr));
  }

  .ts-foot__connect {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
  }

  .ts-foot__connect h2 {
    flex: 1 1 100%;
    margin: 0;
  }

  .ts-foot__cta {
    width: auto;
    margin-bottom: 0;
  }
}

@media (max-width: 989px) {
  /* ts-mobile.css puts the grid on two columns here. */
  .ts-foot__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .ts-foot__cta {
    flex: 1 1 100%;
  }
}

/*
 * TWO PRODUCTS PER ROW ON A PHONE, NOT ONE.
 *
 * ts-mobile.css §1 drops the grid to a single column under 620px and
 * turns the card sideways — photo left, text right — and its comment
 * says the single column is "BY REQUIREMENT, not by taste". The 2026-09
 * brief overrides that: the reference this shop is being drawn to shows
 * two per row on a phone, and the thumbnails are all the same white
 * square now, which is what makes a narrow tile readable. One product
 * per screen also meant the catalogue was six full screens of scrolling.
 *
 * If the single column comes back, this block is the whole change.
 */
@media (max-width: 620px) {
  .ts-products,
  .ts-collection .product-grid {
    --cols: 2;
  }

  .ts-pcard {
    flex-direction: column;
  }

  .ts-pcard__media {
    flex: none;
    width: auto;
    max-width: none;
  }

  .ts-pcard__body {
    justify-content: flex-start;
    padding: 10px 2px 0;
  }

  .ts-pcard__title {
    font-size: 1.1rem;
    -webkit-line-clamp: 2;
    line-clamp: 2;
  }

  .ts-pcard__price {
    font-size: 1.2rem;
  }

  .ts-pcard__add {
    gap: 5px;
    padding: 10px 6px;
    font-size: 1rem;
  }

  .ts-pcard__badge {
    top: 6px;
    left: 6px;
    padding: 3px 7px;
    font-size: 0.85rem;
  }
}

@media (max-width: 749px) {
  /* .ts-wrap's gutter is 16px from here down (ts-mobile.css §4), so the
     20px above is wrong for every full-bleed child that undoes it. */
  :root {
    --ts-gutter: 16px;
  }

  /*
   * THE TAB ROW FITS THE SCREEN, IT DOES NOT SCROLL OFF IT.
   *
   * It used to be a horizontal scroller pulled to the screen edges with
   * `margin-inline: calc(var(--ts-gutter) * -1)` — and --ts-gutter is
   * 20px on :root while .ts-wrap's padding is 16px here, so the strip
   * hung 4px past the viewport on each side and the whole PAGE scrolled
   * sideways. Three short labels have no business scrolling anyway.
   *
   * `grid-auto-flow: column` rather than `repeat(3, 1fr)`: a tab with
   * nothing behind it is not drawn at all (tabs.php), so the count is
   * two or three depending on the catalogue. `minmax(0, 1fr)` is what
   * lets a cell go narrower than its own text instead of pushing the
   * row wide again.
   */
  .ts-tabs__bar {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 0;
    margin-inline: 0;
    padding-inline: 0;
    overflow: visible;
  }

  .ts-tabs__tab {
    min-width: 0;
    padding: 9px 2px 11px;
    /* sized off the viewport so the longest label ("NEW ARRIVALS",
       ~7.3em condensed) still clears a 320px screen's third of a row */
    font-size: clamp(0.9rem, 3.2vw, 1.2rem);
    letter-spacing: 0.02em;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .ts-pcard__title {
    font-size: 1.15rem;
  }

  .ts-pcard__add {
    margin-top: 9px;
    padding-block: 11px;
    font-size: 1.08rem;
  }

  .ts-foot__cta {
    max-width: none;
  }
}

/* ---------- 14. The phone header, drawer and search page ------ */
/*
 * THE 2026-09-28 PHONE PASS. Below 990px the header is drawn the way the
 * big shop apps draw theirs: a slim pink bar — menu, mark, wishlist,
 * account, cart — over a full-width search field, and a side menu that
 * slides in from the LEFT and covers the whole height of the screen.
 *
 * Everything in here that is on screen at first paint is ALSO in
 * ts-critical.css, under "The 2026-09-28 phone pass". That copy is
 * inlined after every <link>, so it wins ties with this file; the two
 * have to say the same thing or the page changes shape when this file
 * lands. Change one, change the other.
 */

/* The bar's height is fixed rather than left to its contents, because
   the catalogue's toolbar sticks directly under it (§16) and needs to
   know where "under" is. 54 + 50 = the two rows. */
@media (max-width: 989px) {
  :root {
    --ts-mnav-h: 104px;
  }
}

/* The announcement strip: ONE line, small, on a phone. It was two lines
   of 17px capitals — 60px of the first screen for one sentence. */
@media (max-width: 749px) {
  .utility-bar__grid.page-width {
    padding-inline: 10px;
  }

  .utility-bar .announcement-bar__message {
    min-height: 0;
    padding: 6px 0;
    font-size: clamp(9px, 2.8vw, 12px);
    line-height: 1.25;
    letter-spacing: 0.04em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* the phone's search row — not drawn at all above 990px */
.ts-msearch {
  display: none;
}

/* the back arrow and the category chips belong to the full-screen search
   page, which only exists below 990px */
.ts-searchbar__back,
.ts-searchbar__browse {
  display: none;
}

/* the drawer's own head and shortcut rows — laid out only in the drawer */
.ts-nav__drawerhead,
.ts-nav__quick {
  display: none;
}

@media (max-width: 989px) {
  /* --- the bar --- */
  .ts-nav__inner {
    min-height: 54px;
    height: 54px;
    padding-block: 0;
    gap: 6px;
  }

  .ts-nav__brand img {
    width: clamp(52px, 15vw, 60px);
  }

  .ts-nav .ts-burger,
  .ts-nav[data-drawer='true'] .ts-burger {
    width: 38px;
    height: 38px;
    margin-left: -8px;
    background: transparent;
    color: #fff;
  }

  .ts-nav .ts-burger svg {
    width: 24px;
    height: 24px;
  }

  .ts-nav__tools {
    margin-left: auto;
    gap: 2px;
  }

  .ts-nav .ts-icon-btn {
    width: 36px;
    height: 36px;
  }

  /* the magnifier's job is done by the search row under the bar */
  .ts-nav__tools [data-ts-search-link] {
    display: none;
  }

  .ts-nav .ts-cart-pill {
    height: 34px;
    margin-left: 4px;
  }

  /* --- the search row --- */
  .ts-msearch {
    display: block;
    height: 50px;
    padding: 2px 0 8px;
  }

  .ts-msearch__bar {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 40px;
    padding: 0 4px 0 14px;
    border-radius: var(--ts-r-pill);
    background: #fff;
    color: var(--ts-muted);
    text-decoration: none;
    box-shadow: 0 2px 10px -4px rgba(90, 10, 50, 0.35);
  }

  .ts-msearch__bar > svg {
    flex: none;
    width: 18px;
    height: 18px;
    fill: none;
    stroke: var(--ts-muted);
    stroke-width: 2.1;
    stroke-linecap: round;
  }

  .ts-msearch__text {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 1.2rem;
    color: var(--ts-muted-2);
  }

  .ts-msearch__text.has-query {
    color: var(--ts-ink);
  }

  .ts-msearch__go {
    flex: none;
    display: grid;
    place-items: center;
    height: 32px;
    padding: 0 14px;
    border-radius: var(--ts-r-pill);
    background: var(--ts-brand);
    color: #fff;
    font-family: var(--ts-font-display);
    font-stretch: var(--ts-display-stretch);
    font-variation-settings: 'wdth' 82;
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: var(--ts-ui-track);
    text-transform: uppercase;
  }

  /* --- the drawer, from the left, full height ---
     It used to drop DOWN out of the bar as a panel under it. It is a
     side sheet now: the whole height of the screen, 86% of its width,
     sliding in from the edge the burger is on. `transform` rather than
     `left`, so the slide is composited and does not lay the page out
     on every frame. */
  .ts-nav__menu {
    inset: 0 auto 0 0;
    width: min(86vw, 340px);
    max-height: none;
    height: 100%;
    padding: 0 0 calc(24px + env(safe-area-inset-bottom, 0px));
    border: 0;
    border-radius: 0 22px 22px 0;
    background: #fff;
    box-shadow: 18px 0 44px -18px rgba(31, 27, 29, 0.45);
    opacity: 1;
    transform: translateX(-104%);
    transition: transform 0.3s var(--ts-out), visibility 0s linear 0.3s;
  }

  .ts-nav[data-drawer='true'] .ts-nav__menu {
    opacity: 1;
    transform: none;
    transition: transform 0.3s var(--ts-out), visibility 0s;
  }

  /* THE DRAWER AND THE SEARCH PAGE BOTH LIVE INSIDE `.ts-nav`, which is
     sticky with z-index 30 — a stacking context. Anything of theirs is
     compared with the rest of the page AT 30, so the WhatsApp button
     (55) and the buy bar (60) painted over an open drawer. While either
     is open the whole bar is lifted over everything instead. */
  html.ts-drawer-open .ts-nav,
  html.ts-search-open .ts-nav {
    z-index: 1000;
  }

  /* The scrim covers the page, and now from the very top: the drawer
     covers the bar too, so there is no bar edge to start from. */
  div.ts-scrim {
    inset: 0;
    z-index: 999;
  }

  /* ...and the strip of the BAR beside the drawer, which the scrim is
     under (it is a sibling at 999, the bar is at 1000). A pseudo-element
     of the bar, so a tap on it lands on `.ts-nav` itself and ts-theme.js
     closes the drawer. */
  .ts-nav::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 35;
    background: rgba(31, 27, 29, 0.34);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.22s var(--ts-ease), visibility 0s linear 0.22s;
  }

  .ts-nav[data-drawer='true']::after {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.22s var(--ts-ease), visibility 0s;
  }

  /* the drawer's rows, in the order an app's side menu has them:
     brand, who you are, where to go, shortcuts */
  .ts-nav__drawerhead {
    order: -3;
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: calc(12px + env(safe-area-inset-top, 0px)) 14px 12px 18px;
    background: var(--ts-brand);
  }

  .ts-nav__drawerlogo img {
    display: block;
    width: 62px;
    height: auto;
  }

  .ts-nav__drawerclose {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    cursor: pointer;
  }

  .ts-nav__drawerclose svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.4;
    stroke-linecap: round;
  }

  /* the header search row replaces the drawer's own field */
  .ts-nav__searchrow {
    display: none;
  }

  .ts-nav__accountrow {
    order: -2;
    margin: 12px 14px 6px;
    padding: 6px 12px;
    border: 0;
    border-radius: 16px;
    background: var(--ts-bg-2);
  }

  .ts-nav__menu > .ts-nav__item {
    padding-inline: 18px;
  }

  .ts-nav__menu .ts-nav__link {
    font-size: 1.2rem;
  }

  .ts-nav__quick {
    order: 1;
    display: block;
    margin-top: 10px;
    padding: 14px 18px 0;
    border-top: 8px solid var(--ts-bg-2);
  }

  .ts-nav__quick-title {
    margin: 0 0 4px;
    font-family: var(--ts-font-display);
    font-stretch: var(--ts-display-stretch);
    font-variation-settings: 'wdth' 82;
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ts-muted);
  }

  .ts-nav__quick-link {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 46px;
    color: var(--ts-ink);
    text-decoration: none;
    font-size: 1.2rem;
    font-weight: 500;
  }

  .ts-nav__quick-link + .ts-nav__quick-link {
    border-top: 1px solid var(--ts-line);
  }

  .ts-nav__quick-link svg {
    flex: none;
    width: 20px;
    height: 20px;
    fill: none;
    stroke: var(--ts-brand);
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .ts-nav__quick-link--wa svg {
    fill: #25d366;
    stroke: none;
  }

  .ts-nav__quick-link span {
    flex: 1 1 auto;
  }

  /* --- the search page ---
     The same #ts-searchbar the magnifier opens as a dropdown between 990
     and 1200px, laid out as a whole screen: back arrow, field, and under
     it the categories until something is typed, then the type-ahead. */
  .ts-searchbar {
    position: fixed;
    inset: 0;
    z-index: 50;
    height: 100%;
    padding: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: #fff;
    border: 0;
    box-shadow: none;
    transform: translateY(14px);
  }

  .ts-nav[data-search='true'] .ts-searchbar {
    transform: none;
  }

  .ts-searchbar > .ts-wrap {
    padding: calc(10px + env(safe-area-inset-top, 0px)) 12px 28px;
  }

  .ts-searchbar__form {
    flex-wrap: wrap;
    gap: 6px;
    padding: 0 0 10px;
    border: 0;
    border-bottom: 1px solid var(--ts-line);
    border-radius: 0;
    background: transparent;
  }

  .ts-searchbar__form:focus-within {
    border-color: var(--ts-line);
    box-shadow: none;
  }

  .ts-searchbar__back {
    flex: none;
    display: grid;
    place-items: center;
    width: 38px;
    height: 42px;
    margin-left: -6px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ts-ink);
    cursor: pointer;
  }

  .ts-searchbar__back svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .ts-searchbar__form input[type='search'] {
    height: 42px;
    padding: 0 16px;
    border-radius: var(--ts-r-pill);
    background: var(--ts-bg-2);
    box-shadow: inset 0 0 0 1px var(--ts-line);
  }

  .ts-searchbar__form input[type='search']:focus,
  .ts-searchbar__form input[type='search']:focus-visible {
    box-shadow: inset 0 0 0 1.5px var(--ts-brand);
  }

  .ts-searchbar__go {
    width: 42px;
    height: 42px;
  }

  /* the back arrow is the close button here */
  .ts-searchbar__close {
    display: none;
  }

  .ts-searchbar .ts-predictive {
    position: static;
    flex: 1 0 100%;
    max-height: none;
    margin-top: 6px;
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .ts-searchbar__browse {
    display: block;
    padding-top: 18px;
  }

  /* the chips are what to do BEFORE typing; once the type-ahead has
     something to show, it is the answer and they are in its way */
  .ts-searchbar:has(.ts-predictive:not([hidden])) .ts-searchbar__browse {
    display: none;
  }

  .ts-searchbar__label {
    margin: 0 0 10px;
    font-family: var(--ts-font-display);
    font-stretch: var(--ts-display-stretch);
    font-variation-settings: 'wdth' 82;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ts-muted);
  }

  .ts-searchbar__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .ts-searchbar__chip {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 0 14px;
    border-radius: var(--ts-r-pill);
    background: var(--ts-bg-2);
    color: var(--ts-ink);
    text-decoration: none;
    font-size: 1.15rem;
  }

  html.ts-search-open,
  html.ts-search-open body {
    overflow: hidden;
  }

  /* on a results page the header row already carries the query, so the
     second field in the page header is one field too many */
  .ts-collhead__search {
    display: none;
  }
}

/* --- the hero eyebrow sits at the TOP of the card, desktop only ---
   The copy column is centred against the taller pack column, so the
   "Premium Beauty" pill floated a third of the way down the card with
   empty pink above it. The column now stretches to the grid's height,
   the pill takes the top, and the rest stays centred in what is left
   (auto margins either side). Below 990px the phone banner owns this.
   Mirrored in ts-critical.css — it is above the fold. */
@media (min-width: 990px) {
  .ts-hero__copy {
    align-self: stretch;
    display: flex;
    flex-direction: column;
  }

  .ts-hero__eyebrow {
    align-self: flex-start;
    margin-bottom: auto;
  }

  .ts-hero__title {
    margin-top: 16px;
  }

  .ts-hero__copy > :last-child {
    margin-bottom: auto;
  }
}

/* --- the home page's first screen, on a phone or tablet (below 990px) ---
   THE TABS HAVE TO BE ON THE FIRST SCREEN. The hero was 1004px tall on a
   390px phone — the pack, its caption, six swatches, the eyebrow, the
   headline, two lines of copy, two buttons and three stats — and the four
   trust cards under it were another 209. "New Arrivals / Trending Now /
   Gift Sets" started 1353px down, a screen and a half below the fold.

   Now the hero is a banner: the headline and one button on the left, the
   pack on the right at a third of the width. The caption, the swatch row,
   the second button, the stats and the seal are hidden — each of them is
   on the pack's own category page — and the trust strip is gone from the
   home page on a phone (it is still on the product and catalogue pages,
   where the promise is next to the thing being bought). */
@media (max-width: 989px) {
  .ts-hero {
    padding-block: 10px 0;
  }

  .ts-hero__card {
    border-radius: 18px;
  }

  .ts-hero__grid {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
    align-items: center;
    gap: 6px;
    padding: 16px 12px 16px 18px;
    text-align: left;
  }

  .ts-build {
    order: 0;
    gap: 0;
  }

  .ts-build__stage {
    width: 100%;
    max-width: clamp(140px, 28vw, 240px);
  }

  .ts-build__hang {
    --hang-w: 58px;
  }

  .ts-build__hud,
  .ts-hero__seal,
  .ts-hero__sub,
  .ts-hero__stats,
  .ts-hero__actions .ts-btn--ghost {
    display: none;
  }

  .ts-hero__eyebrow {
    margin-bottom: 8px;
    padding: 4px 9px;
    font-size: 0.85rem;
  }

  .ts-hero__title {
    margin: 0 0 12px;
    font-size: clamp(2rem, 6.6vw, 3.4rem);
    line-height: 1.02;
  }

  .ts-hero__actions {
    justify-content: flex-start;
    margin: 0;
  }

  .ts-hero .ts-btn--lg {
    min-height: 38px;
    padding: 9px 16px;
    font-size: 1.05rem;
  }

}

@media (max-width: 749px) {
  .ts-hero + .ts-section-trust {
    display: none;
  }
}

/* ---------- 15. The wishlist ---------------------------------- */
/* See the head of inc/wishlist.php. The hearts are printed on every card
   and only drawn under `html.ts-js`: the list is kept by the script, so
   without it a heart is a button that can do nothing. */
.ts-wish {
  display: none;
  place-items: center;
  padding: 0;
  border: 0;
  cursor: pointer;
  color: var(--ts-ink);
  -webkit-tap-highlight-color: transparent;
}

html.ts-js .ts-wish {
  display: grid;
}

.ts-wish svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linejoin: round;
  transition: fill 0.18s var(--ts-ease);
}

.ts-wish.is-on {
  color: var(--ts-brand);
}

.ts-wish.is-on svg {
  fill: currentColor;
}

.ts-wish.is-popped svg {
  animation: ts-wish-pop 0.38s var(--ts-out);
}

@keyframes ts-wish-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.3); }
  100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .ts-wish.is-popped svg {
    animation: none;
  }
}

/* on a card: a round button over the top right of the photo, opposite
   the discount chip */
.ts-wish--icon {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 3;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 2px 10px -2px rgba(31, 27, 29, 0.18);
}

.ts-wish--icon:hover {
  color: var(--ts-brand);
}

@media (max-width: 620px) {
  .ts-wish--icon {
    top: 6px;
    right: 6px;
    width: 30px;
    height: 30px;
  }

  .ts-wish--icon svg {
    width: 16px;
    height: 16px;
  }
}

/* on the product page: a full-width outline pill under Add to cart */
html.ts-js .ts-wish--full {
  display: flex;
}

.ts-wish--full {
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 46px;
  margin-top: 10px;
  border: 1.5px solid var(--ts-line-2);
  border-radius: var(--ts-r-pill);
  background: #fff;
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
}

.ts-wish--full:hover,
.ts-wish--full.is-on {
  border-color: var(--ts-brand);
  color: var(--ts-brand);
}

.ts-wish__on,
.ts-wish--full.is-on .ts-wish__off {
  display: none;
}

.ts-wish--full.is-on .ts-wish__on {
  display: inline;
}

/* the count beside the header's heart and in the drawer */
.ts-wish-link {
  position: relative;
}

.ts-wish-link svg {
  stroke-width: 1.8;
}

.ts-wish-count {
  display: grid;
  place-items: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 99px;
  font-size: 0.85rem;
  font-weight: 800;
  line-height: 1;
}

.ts-wish-count[hidden] {
  display: none;
}

.ts-wish-link .ts-wish-count {
  position: absolute;
  top: 2px;
  right: 0;
  background: #fff;
  color: var(--ts-brand);
}

.ts-nav__quick .ts-wish-count {
  min-width: 22px;
  height: 22px;
  background: var(--ts-brand);
  color: #fff;
}

/* the page */
.ts-wishpage {
  padding-bottom: 40px;
}

.ts-wishpage__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  margin: 8px 0 20px;
}

.ts-wishpage__count {
  margin: 0;
  color: var(--ts-muted);
}

.ts-wishpage.is-loading .ts-wishpage__grid {
  min-height: 320px;
  opacity: 0.5;
}

.ts-wishpage__grid:empty {
  display: none;
}

/* ---------- 16. The catalogue on a phone ---------------------- */
/*
 * TWO BUTTONS OVER THE GRID, AND BOTH OPEN A SHEET FROM THE BOTTOM.
 *
 * The toolbar was a Filters pill, "Showing 1–24 of 107 results" and a
 * 280px sort pill wrapping onto a second line, under a pink band holding
 * the page title and "107 products" — 300px of controls before the first
 * product. It is one strip now, Sort | Filter, the way the big shop apps
 * lay it out, and it sticks under the header so it is there when the
 * shopper is twenty products down and changes their mind.
 */
.ts-filters__reset.is-idle {
  display: none;
}

/* /shop/ needs no heading band, at any width: the header and the grid say
   where you are, and the toolbar says how many. The <h1> is still in the
   page for search engines and screen readers — only the band is hidden. A
   category keeps its title, because there it IS the answer to "where am
   I" (slim, on a phone — below). */
.post-type-archive-product:not(.search) .ts-collhead {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (max-width: 989px) {

  .ts-collhead {
    padding-block: 10px 4px;
    background: transparent;
  }

  .ts-collhead__title {
    font-size: 1.7rem;
  }

  /* the toolbar starts right under the header — ts-fixes.css §3 gave the
     section 22px of top padding to hold it off a tinted band that is not
     drawn here any more */
  .ts-collection {
    padding-top: 0;
  }

  .ts-facetbar {
    position: sticky;
    top: var(--ts-mnav-h, 104px);
    z-index: 20;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0;
    margin: 0 calc(var(--ts-gutter) * -1) 12px;
    padding: 0;
    border-top: 0;
    border-bottom: 1px solid var(--ts-line);
    background: #fff;
    box-shadow: 0 6px 12px -12px rgba(31, 27, 29, 0.4);
  }

  /* the sheet is inside the strip, and a sticky element with a z-index
     is a stacking context — so while it is open the strip goes over
     everything, or the header paints over the top of the scrim */
  .ts-facetbar:has(.ts-sort[data-open='true']) {
    z-index: 1001;
  }

  .ts-facetbar .woocommerce-result-count,
  .ts-facetbar__spacer {
    display: none;
  }

  .ts-facetbar .woocommerce-ordering {
    order: 1;
    min-width: 0;
    margin: 0;
  }

  .ts-facetbar .ts-filters__open {
    order: 2;
  }

  .ts-facetbar .ts-sort,
  .ts-facetbar .woocommerce-ordering select {
    width: 100%;
  }

  /* the two cells, identical */
  .ts-facetbar .ts-sort__btn,
  .ts-facetbar .ts-filters__open {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    min-width: 0;
    max-width: none;
    height: 46px;
    min-height: 0;
    padding: 0 10px;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    color: var(--ts-ink);
    font-family: var(--ts-font-display);
    font-stretch: var(--ts-display-stretch);
    font-variation-settings: 'wdth' 82;
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: var(--ts-ui-track);
    text-transform: uppercase;
  }

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

  .ts-facetbar .ts-sort__value {
    flex: 0 1 auto;
  }

  .ts-facetbar .ts-sort__btn[aria-expanded='true'] {
    color: var(--ts-brand);
    box-shadow: none;
  }

  /* --- the sort sheet ---
     The listbox ts-facets.js builds, laid out as a sheet from the bottom
     of the screen. The scrim is a pseudo-element of `.ts-sort`, so a tap
     on it is a tap on the control itself, and ts-facets.js closes on
     that. */
  .ts-sort[data-open='true']::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 1;
    background: var(--ts-backdrop);
  }

  .ts-facetbar .ts-sort__panel {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 2;
    width: auto;
    min-width: 0;
    max-width: none;
    max-height: 72vh;
    overflow-y: auto;
    padding: 26px 12px calc(14px + env(safe-area-inset-bottom, 0px));
    border: 0;
    border-radius: 22px 22px 0 0;
    box-shadow: 0 -12px 40px -16px rgba(31, 27, 29, 0.4);
    transform: translateY(100%);
    transition: transform 0.28s var(--ts-out), visibility 0s linear 0.28s;
  }

  .ts-facetbar .ts-sort[data-open='true'] .ts-sort__panel {
    transform: none;
    transition: transform 0.28s var(--ts-out), visibility 0s;
  }

  /* the grab handle, which says "this is a sheet" */
  .ts-facetbar .ts-sort__panel::before,
  .ts-filters__head::before {
    content: '';
    position: absolute;
    top: 9px;
    left: 50%;
    width: 38px;
    height: 4px;
    margin-left: -19px;
    border-radius: 4px;
    background: var(--ts-line-2);
  }

  .ts-facetbar .ts-sort__opt {
    min-height: 50px;
    padding-inline: 12px;
    font-size: 1.25rem;
  }

  /* --- the filter sheet ---
     A sheet from the bottom, not a screen from the side: it was a
     full-width page on a phone with the grid gone behind it, and its
     Apply button was pinned over the bottom of the list with a negative
     margin — "On sale" sat half under a 52px pink pill. Now the form is
     the scroller and the footer is the last thing in it, sticky at the
     bottom, so at the end of the scroll it sits UNDER the last option
     rather than on top of it. */
  .ts-filters {
    z-index: 1001;
  }

  .ts-filters__panel {
    inset: auto 0 0 0;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-height: 88vh;
    padding: 0;
    border-radius: 22px 22px 0 0;
    overflow: hidden;
    animation: ts-sheet-up 0.3s var(--ts-out);
  }

  @keyframes ts-sheet-up {
    from {
      transform: translateY(100%);
    }
  }

  .ts-filters__head {
    position: relative;
    flex: none;
    margin: 0;
    padding: 24px 16px 12px;
    border-bottom: 1px solid var(--ts-line);
  }

  .ts-filters__form {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 0 16px;
  }

  .ts-filters__actions {
    position: sticky;
    bottom: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
    gap: 10px;
    margin: 12px -16px 0;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--ts-line);
    background: #fff;
    box-shadow: 0 -8px 16px -14px rgba(31, 27, 29, 0.35);
  }

  .ts-filters.is-open .ts-filters__reset,
  .ts-filters.is-open .ts-filters__reset.is-idle {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 44px;
    border: 1.5px solid var(--ts-line-2);
    border-radius: var(--ts-r-pill);
    color: var(--ts-ink);
    text-decoration: none;
    font-family: var(--ts-font-display);
    font-stretch: var(--ts-display-stretch);
    font-variation-settings: 'wdth' 82;
    font-size: 1.1rem;
    font-weight: 700;
    letter-spacing: var(--ts-ui-track);
    text-transform: uppercase;
  }

  .ts-filters__actions .ts-filters__apply {
    order: 1;
    height: 44px;
    min-height: 0;
    padding: 0 12px;
    box-shadow: none;
    font-size: 1.1rem;
  }
}

/* ---------- 17. Small repairs --------------------------------- */
/*
 * THE BOX INSIDE THE DESKTOP SEARCH PILL. base.css gives every focused
 * element a ring — a white 3px band plus a soft dark halo, drawn as
 * box-shadow — and the field inside the header's pill picked it up, so
 * clicking into search drew a hard white rectangle with a grey shadow
 * inside the round pill. The pill already shows focus (§3,
 * `:focus-within`); the field inside it must not. The phone's search
 * field had this fix; the desktop pill did not.
 */
.ts-search input[type='search']:focus,
.ts-search input[type='search']:focus-visible,
.ts-search input[type='search'].focused {
  outline: 0;
  box-shadow: none;
  background: transparent;
}

.ts-search input[type='search']::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

/* The product page's Add to cart says "Added to cart" in mint for a
   moment, the way a card's does, now that it no longer reloads the page
   (assets/js/ts-shop.js). `!important` because WooCommerce and Dawn each
   draw this button with a stack of their own selectors, and a one-second
   confirmation is not worth out-weighing all of them. */
.single_add_to_cart_button.is-added,
.single_add_to_cart_button.is-added:hover,
.single_add_to_cart_button.is-added:focus-visible {
  background: var(--ts-mint) !important;
  border-color: var(--ts-mint) !important;
  color: #fff !important;
}

.single_add_to_cart_button.is-added svg {
  width: 18px;
  height: 18px;
  margin-right: 6px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -3px;
}

.single_add_to_cart_button.is-busy {
  opacity: 0.7;
  pointer-events: none;
}

/* ---------- 18. The product page's assurances ----------------- */
/*
 * In stock / Delivered in / Cash on delivery, under Add to cart
 * (template-parts/product-assurance.php; the base layer is ts-fixes.css
 * §15e and every rule here is the same weight, winning on order).
 *
 * The block was the last blush-tinted card on the product page — a pale
 * pink box with body-weight headings, and its icons drawn as solid black
 * blobs, because nothing gave these SVGs `fill: none` and a stroke-only
 * path filled with the default black is a silhouette. It is drawn the way
 * the rest of the skin is now: white, a hairline, condensed capitals for
 * the line a shopper reads as UI, and each icon as a pink stroke inside a
 * soft pink disc — the one accent, used once per row.
 *
 * `--ts-out` in the base layer is an EASING, not a colour, so the
 * out-of-stock state never had one. It is muted ink here.
 */
.ts-assure {
  margin: 18px 0 4px;
}

.ts-assure__list {
  border: 1px solid var(--ts-line);
  border-radius: var(--ts-r);
  background: #fff;
}

.ts-assure__row {
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
}

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

.ts-assure__badge {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--ts-brand-wash);
  color: var(--ts-brand);
  flex: none;
}

.ts-assure__icon,
.ts-assure__link svg,
.ts-assure__wa .ts-assure__go {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ts-assure__icon {
  width: 19px;
  height: 19px;
  margin: 0;
  color: inherit;
}

.ts-assure__text {
  gap: 3px;
}

.ts-assure__text b,
.ts-assure__wa b {
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--ts-ink);
}

.ts-assure__text small,
.ts-assure__wa small {
  color: var(--ts-muted);
  font-size: 1.0833rem;
  line-height: 1.45;
}

/* In stock carries a live dot, in the mint the Added-to-cart state
   already uses — the only non-pink colour here, and the one that means
   "yes" everywhere else in the shop. */
.ts-assure__row--stock:not(.is-out) .ts-assure__text b::before {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-inline-end: 7px;
  border-radius: 50%;
  background: var(--ts-mint);
  box-shadow: 0 0 0 3px rgb(47 138 78 / 16%);
  vertical-align: 2px;
}

.ts-assure__text b.ts-assure__low {
  color: var(--ts-brand);
}

.ts-assure__row--stock.is-out .ts-assure__badge {
  background: rgb(23 21 26 / 6%);
  color: var(--ts-muted);
}

.ts-assure__row--stock.is-out .ts-assure__text b {
  color: var(--ts-muted);
}

.ts-assure__link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-inline-start: 8px;
  color: var(--ts-brand);
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
  text-decoration: none;
  vertical-align: 1px;
}

.ts-assure__link svg {
  width: 13px;
  height: 13px;
  stroke-width: 2.2;
  transition: transform 0.2s ease;
}

.ts-assure__link:hover,
.ts-assure__link:focus-visible {
  color: var(--ts-brand-700);
}

.ts-assure__link:hover svg {
  transform: translateX(2px);
}

@media screen and (max-width: 480px) {
  .ts-assure__link {
    display: flex;
    width: fit-content;
    margin: 4px 0 0;
  }
}

/* The WhatsApp row: white like the list above it, the brand mark in its
   own green disc, and an arrow that says it leaves the page. */
.ts-assure__wa {
  gap: 14px;
  margin-top: 10px;
  padding: 12px 16px;
  border: 1px solid var(--ts-line);
  border-radius: var(--ts-r);
  background: #fff;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.ts-assure__wa:hover,
.ts-assure__wa:focus-visible {
  border-color: rgb(37 211 102 / 55%);
  background: #fff;
  box-shadow: 0 10px 22px -16px rgb(37 211 102 / 60%);
}

.ts-assure__wa > svg:first-child {
  width: 38px;
  height: 38px;
  padding: 9px;
  border-radius: 50%;
  background: #25d366;
  color: #fff;
  box-sizing: border-box;
}

.ts-assure__wa span {
  flex: 1 1 auto;
  gap: 3px;
}

.ts-assure__wa .ts-assure__go {
  width: 18px;
  height: 18px;
  color: var(--ts-muted);
  flex: none;
  transition: transform 0.2s ease, color 0.2s ease;
}

.ts-assure__wa:hover .ts-assure__go {
  color: #25d366;
  transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
  .ts-assure__link svg,
  .ts-assure__go {
    transition: none;
  }
}

/* ---------- 19. Share this product ---------------------------- */
/*
 * template-parts/product-share.php — a row of round buttons under the
 * SKU. At rest every one is the same white circle with an ink glyph, so
 * six brand colours do not line up beside the pink Add to cart as six
 * more things shouting; the platform's own colour arrives on hover and
 * focus, which is when it helps to confirm where the tap is going.
 *
 * Social glyphs are FILLED (ts_social_icon), the link / check / share
 * glyphs are STROKES (ts_icon) — each gets the fill it needs, or a
 * stroke-only path paints as a black blob (see §18).
 *
 * The phone's share sheet ("Share", navigator.share) is printed `hidden`
 * and shown only on a touch screen whose browser has the API:
 * ts-theme.js sets `html.ts-can-share`. Copy link needs the script too,
 * so it is drawn only under `html.ts-js`.
 */
.ts-share {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin: 0 0 18px;
  padding-top: 16px;
  border-top: 1px solid var(--ts-line);
}

.ts-share__label {
  margin: 0;
  font-family: var(--ts-font-display);
  font-stretch: var(--ts-display-stretch);
  font-variation-settings: 'wdth' 82;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: var(--ts-ui-track);
  text-transform: uppercase;
  color: var(--ts-ink);
}

.ts-share__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ts-share__item {
  margin: 0;
}

.ts-share__item--copy {
  display: none;
}

html.ts-js .ts-share__item--copy {
  display: block;
}

@media (pointer: coarse) {
  html.ts-can-share .ts-share__item--native {
    display: block;
  }
}

.ts-share__btn {
  --ts-share-c: var(--ts-brand);
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin: 0;
  padding: 0;
  border: 1.5px solid var(--ts-line-2);
  border-radius: 50%;
  background: #fff;
  color: var(--ts-ink);
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.2s ease, border-color 0.2s ease,
    color 0.2s ease, transform 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}

.ts-share__btn svg {
  width: 17px;
  height: 17px;
  pointer-events: none;
}

a.ts-share__btn svg {
  fill: currentColor;
  stroke: none;
}

button.ts-share__btn svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ts-share__btn--whatsapp { --ts-share-c: #25d366; }
.ts-share__btn--facebook { --ts-share-c: #1877f2; }
.ts-share__btn--pinterest { --ts-share-c: #e60023; }
.ts-share__btn--x { --ts-share-c: #000; }
.ts-share__btn--telegram { --ts-share-c: #229ed9; }
.ts-share__btn--copy { --ts-share-c: var(--ts-ink); }

.ts-share__btn:hover,
.ts-share__btn:focus-visible {
  border-color: var(--ts-share-c);
  background: var(--ts-share-c);
  color: #fff;
  transform: translateY(-2px);
}

/* the phone's share sheet: filled ink, so it reads as the main one */
.ts-share__btn--native {
  border-color: var(--ts-ink);
  background: var(--ts-ink);
  color: #fff;
}

.ts-share__btn--native span {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.ts-share__ico-done,
.ts-share__btn--copy.is-copied .ts-share__ico-link {
  display: none;
}

.ts-share__btn--copy.is-copied .ts-share__ico-done {
  display: block;
}

.ts-share__btn--copy.is-copied {
  border-color: var(--ts-mint);
  background: var(--ts-mint);
  color: #fff;
}

.ts-share__toast {
  flex-basis: 100%;
  min-height: 0;
  margin: -2px 0 0;
  font-size: 1.0833rem;
  font-weight: 600;
  color: var(--ts-mint);
}

.ts-share__toast:empty {
  display: none;
}

@media (max-width: 619px) {
  .ts-share {
    gap: 10px;
  }

  .ts-share__label {
    flex-basis: 100%;
  }

  /* seven 40px circles and six 7px gaps is 322px: one row down to a
     360px phone */
  .ts-share__list {
    gap: 7px;
  }
}

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

  .ts-share__btn:hover,
  .ts-share__btn:focus-visible {
    transform: none;
  }
}

/* Rhode gift offer — product-first layout, shared Archivo and brand pink. */
html.ts-rhode-open { overflow: hidden; }
.ts-rhode { border: 0; padding: 0; width: min(920px, calc(100vw - 32px)); max-width: none; max-height: calc(100dvh - 24px); overflow: auto; border-radius: 22px; background: #fff; color: var(--ts-ink, #17151a); box-shadow: 0 30px 100px #25132240; }
.ts-rhode:not([open]) { display: none; }
.ts-rhode::backdrop { background: #25132299; backdrop-filter: blur(4px); }
.ts-rhode__close { position: sticky; top: 8px; float: right; margin: 8px 10px -52px 0; z-index: 5; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 1px solid #e8dce2; border-radius: 50%; background: #fff; color: #17151a; font: 28px/1 Arial, sans-serif; cursor: pointer; }
.ts-rhode a:focus-visible, .ts-rhode button:focus-visible { outline: 3px solid var(--ts-accent, #e31c79); outline-offset: 3px; }
.ts-rhode__masthead { min-height: 70px; display: flex; align-items: center; gap: 18px; padding: 9px 68px 9px 24px; border-bottom: 1px solid #f4e3eb; }
.ts-rhode__logo { display: block; width: 76px; height: 54px; object-fit: contain; }
.ts-rhode__masthead > span { font-size: 11px; color: #765868; text-transform: uppercase; letter-spacing: .08em; }
.ts-rhode__layout { display: grid; grid-template-columns: 52% 48%; }
.ts-rhode__visual { min-width: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 12px; background: #fff; border-right: 1px solid #f4e3eb; }
.ts-rhode__stage { display: block; position: relative; width: 100%; aspect-ratio: 8 / 9; isolation: isolate; background: #fff; }
.ts-rhode__frame { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; opacity: 0; transition: opacity .26s linear; }
.ts-rhode__frame.is-current { opacity: 1; }
.ts-rhode__caption { text-align: center; margin: 4px 0 8px; font-size: 11px; color: #6b5261; }
.ts-rhode__copy { padding: 24px 28px; background: #fff6fa; }
.ts-rhode__urgency { display: grid; justify-items: start; gap: 7px; }
.ts-rhode__offer { display: inline-flex; align-items: center; gap: 7px; background: #ac0955; color: #fff; padding: 6px 11px; border-radius: 30px; font-size: 11px; line-height: 1.2; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; }
.ts-rhode__offer::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: #ffd3e7; }
.ts-rhode__deadline-label { font-size: 12px; color: #6b2447; }
.ts-rhode__countdown { display: flex; align-items: center; gap: 7px; }
.ts-rhode__countdown > span { display: grid; justify-items: center; min-width: 43px; padding: 6px 8px; border: 1px solid #eec8da; border-radius: 8px; background: #fff; }
.ts-rhode__countdown b { font: 800 23px/1 var(--ts-font-display); font-variant-numeric: tabular-nums; }
.ts-rhode__countdown small { margin-top: 3px; font-size: 8px; line-height: 1; text-transform: uppercase; letter-spacing: .06em; }
.ts-rhode__countdown i { font-style: normal; color: #9b6680; }
.ts-rhode__ends { font-size: 10px; color: #785364; }
.ts-rhode h2 { margin: 17px 0 7px; font-size: 34px; line-height: 1.04; letter-spacing: -.7px; font-weight: 800; text-transform: uppercase; }
.ts-rhode h2 em { font-style: normal; color: var(--ts-accent, #e31c79); }
.ts-rhode__name { margin: 0 0 7px; font-size: 16px; font-weight: 750; }
#ts-rhode-desc { font-size: 12px; line-height: 1.5; margin: 0; color: #604e58; }
.ts-rhode__features { padding: 0; margin: 12px 0; list-style: none; display: flex; flex-wrap: wrap; gap: 7px 12px; font-size: 11px; }
.ts-rhode__features li::before { content: '✓'; color: var(--ts-accent, #e31c79); margin-right: 5px; font-weight: 800; }
.ts-rhode__price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; margin: 15px 0; }
.ts-rhode__price strong { color: var(--ts-accent, #e31c79); font-size: 31px; line-height: 1; font-family: var(--ts-font-display); font-variation-settings: 'wdth' 82; }
.ts-rhode__price s { font-size: 15px; color: #77636e; }
.ts-rhode__price > span { font-size: 10px; color: #773355; border: 1px solid #efc7db; border-radius: 20px; padding: 4px 7px; }
.ts-rhode .ts-rhode__shop { display: flex; width: 100%; min-height: 46px; justify-content: center; font-size: 14px; padding: 10px 16px; }
.ts-rhode__sharing { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 7px; margin-top: 10px; }
.ts-rhode__share { display: flex; justify-content: center; align-items: center; gap: 5px; min-width: 0; min-height: 44px; padding: 6px 4px; border: 1px solid #e4d3dd; border-radius: 10px; background: #fff; font-family: inherit; font-size: 10px; font-weight: 650; line-height: 1.2; text-decoration: none; cursor: pointer; }
.ts-rhode__share--whatsapp { color: #166443; border-color: #c7dbd1; }
.ts-rhode__share--instagram { color: #a92464; border-color: #ecc1d7; }
.ts-rhode__share--facebook { color: #2358a4; border-color: #c6d6ed; }
.ts-rhode__share svg { flex: 0 0 16px; width: 16px; height: 16px; fill: currentColor; }
.ts-rhode__share:hover { background: #fff9fc; }
.ts-rhode__share-status { margin: 0; font-size: 11px; line-height: 1.5; }
.ts-rhode__share-status:not(:empty) { margin-top: 8px; }
.ts-rhode__instagram-help { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; font-size: 12px; }
.ts-rhode__instagram-help[hidden] { display: none; }
.ts-rhode__instagram-help input { width: 100%; min-width: 0; border: 1px solid #dbc4d0; border-radius: 6px; padding: 8px; font-size: 16px; }
.ts-rhode__instagram-help a { color: #a92464; padding-block: 5px; }
.ts-rhode__contact { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 12px; padding-top: 10px; border-top: 1px solid #ead9e1; font-size: 10px; line-height: 1.5; }
.ts-rhode__contact a { color: #4e3543; text-underline-offset: 3px; overflow-wrap: anywhere; }
.ts-rhode__lights { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
.is-open > .ts-rhode__lights { opacity: 1; }
.ts-rhode__lights i { position: absolute; width: 8%; aspect-ratio: 1; transform: translate(-50%, -50%); border-radius: 50%; background: radial-gradient(circle, #fffde8 0%, #ffde78cc 12%, #ffbd4277 32%, #ffba4000 70%); animation: ts-fairy-twinkle 1.8s ease-in-out infinite alternate; animation-play-state: paused; }
.is-open > .ts-rhode__lights i { animation-play-state: running; }
.ts-rhode__lights i:nth-child(1) { left: 31.5%; top: 13%; }
.ts-rhode__lights i:nth-child(2) { left: 55%; top: 13%; animation-delay: -.7s; }
.ts-rhode__lights i:nth-child(3) { left: 28%; top: 23%; animation-delay: -1.2s; }
.ts-rhode__lights i:nth-child(4) { left: 73%; top: 27%; animation-delay: -.4s; }
.ts-rhode__lights i:nth-child(5) { left: 33%; top: 46%; animation-delay: -1s; }
.ts-rhode__lights i:nth-child(6) { left: 70%; top: 48%; animation-delay: -.2s; }
.ts-rhode__lights i:nth-child(7) { left: 71%; top: 60%; animation-delay: -1.5s; }
.ts-rhode__lights i:nth-child(8) { left: 66%; top: 82%; animation-delay: -.8s; }
@keyframes ts-fairy-twinkle { from { opacity: .05; } to { opacity: 1; } }
.ts-build__rhode[hidden] { display: none; }
.ts-build__rhode { position: absolute; inset: 8% 0; width: 100%; height: 84%; border-radius: 12px; overflow: hidden; opacity: 0; transform: translateY(5%) scale(.93); transition: opacity .55s linear, transform .85s var(--ts-out); }
.ts-build__rhode.is-in { opacity: 1; transform: none; }
.ts-build.is-rhode .ts-build__cup, .ts-build.is-rhode .ts-build__shadow { visibility: hidden; }
.ts-gift-message { flex-basis: 100%; width: 100%; margin-bottom: 16px; }
.ts-gift-message label { display: block; margin-bottom: 8px; font-size: 14px; font-weight: 700; }
.ts-gift-message label span { font-weight: 400; }
.ts-gift-message textarea { display: block; width: 100%; min-height: 86px; resize: vertical; border: 1px solid #d7c8d0; border-radius: 12px; padding: 12px; background: #fff; color: #17151a; font: inherit; font-size: 16px; }
.ts-gift-message small { display: block; margin-top: 6px; font-size: 12px; line-height: 1.5; }
@media (max-width: 640px) {
  .ts-rhode { width: min(380px, calc(100vw - 28px)); max-height: calc(100dvh - 40px); border-radius: 18px; }
  .ts-rhode__masthead { min-height: 42px; padding: 3px 58px 3px 14px; gap: 10px; }
  .ts-rhode__logo { width: 48px; height: 34px; }
  .ts-rhode__close { top: 4px; margin-top: 4px; margin-right: 6px; }
  .ts-rhode__masthead > span { font-size: 8px; max-width: 145px; }
  .ts-rhode__layout { grid-template-columns: 1fr; }
  .ts-rhode__visual { padding: 0 10px; border-right: 0; }
  /* Reserve room for every control before sizing the complete, uncropped photo. */
  .ts-rhode__visual .ts-rhode__stage { height: clamp(140px, calc(84dvh - 366px), 290px); width: auto; max-width: 100%; max-height: none; flex: none; }
  .ts-rhode__caption { display: none; }
  .ts-rhode__copy { padding: 9px 14px 10px; }
  .ts-rhode__urgency { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px 8px; align-items: center; }
  .ts-rhode__offer { max-width: 100%; font-size: 10px; padding: 5px 7px; letter-spacing: .04em; }
  .ts-rhode__offer::before { flex-shrink: 0; }
  .ts-rhode__deadline-label { grid-column: 2; min-width: 0; font-size: 10px; line-height: 1.4; text-align: right; justify-self: end; }
  /* Give all four units a full row so digits and labels fit comfortably. */
  .ts-rhode__countdown { grid-column: 1 / -1; grid-row: 2; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; min-width: 0; gap: 7px; }
  .ts-rhode__countdown > span { box-sizing: border-box; width: 100%; min-width: 0; padding: 6px 4px 5px; border-radius: 10px; box-shadow: 0 2px 5px #ac095508; }
  .ts-rhode__countdown b { font-size: clamp(22px, 6vw, 26px); color: #ac0955; letter-spacing: 0; }
  .ts-rhode__countdown small { margin-top: 3px; font-size: 9px; line-height: 1.2; letter-spacing: .04em; }
  .ts-rhode__countdown i { display: none; }
  .ts-rhode__ends { grid-column: 1 / -1; justify-self: center; font-size: 10px; line-height: 1.4; text-align: center; }
  .ts-rhode h2 { font-size: 20px; margin: 7px 0 3px; }
  .ts-rhode__name { font-size: 12px; line-height: 1.3; margin-bottom: 3px; }
  #ts-rhode-desc { display: none; }
  .ts-rhode__features { gap: 4px 8px; font-size: 9px; line-height: 1.4; margin: 5px 0; }
  .ts-rhode__price { margin: 7px 0; gap: 8px; }
  .ts-rhode__price strong { font-size: 25px; }
  .ts-rhode__price s { font-size: 13px; }
  .ts-rhode__price > span { font-size: 9px; padding: 3px 6px; }
  .ts-rhode .ts-rhode__shop { min-height: 44px; padding-block: 8px; font-size: 13px; }
  .ts-rhode__sharing { margin-top: 6px; gap: 5px; }
  .ts-rhode__share { min-height: 38px; font-size: 9px; }
  .ts-rhode__contact { gap: 2px 8px; margin-top: 6px; padding-top: 6px; font-size: 9px; line-height: 1.4; }
}
@media (prefers-reduced-motion: reduce) {
  .ts-rhode__frame, .ts-build__rhode { transition: none; }
  .ts-rhode__lights i { animation: none; opacity: .65; }
}
