/*
 * WooCommerce, restyled to the Xyvira design system.
 *
 * WooCommerce's own general/layout stylesheets are dequeued in functions.php,
 * so this file is not a set of overrides — it is the styling. Anything not
 * covered here renders unstyled.
 */

.x-skip {
  position: absolute;
  left: -9999px;
}
.x-skip:focus {
  left: 1rem;
  top: 1rem;
  z-index: 100;
  background: var(--x-dark);
  color: var(--x-bg);
  padding: 0.75rem 1.25rem;
  border-radius: var(--x-r-pill);
}

.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap;
}

.x-shop { padding-block: 2rem 3rem; }
@media (min-width: 1024px) { .x-shop { padding-block: 3rem 4rem; } }

/* ── Archive header ────────────────────────────────────────────────────────── */

.woocommerce-products-header { margin-bottom: 2rem; }

.woocommerce-products-header__title,
.x-shop h1.page-title {
  font-family: var(--font-display);
  font-size: 2rem;
  line-height: 1.15;
  margin: 0;
}
@media (min-width: 1024px) {
  .woocommerce-products-header__title { font-size: 2.75rem; }
}

.term-description { color: var(--x-ink-soft); font-size: 0.9375rem; max-width: 40rem; }

.woocommerce-result-count {
  color: var(--x-muted);
  font-size: 0.8125rem;
  margin: 0 0 1rem;
}

.woocommerce-ordering select,
.x-shop select {
  appearance: none;
  border: 1px solid var(--x-line);
  background: var(--x-field);
  border-radius: var(--x-r-md);
  padding: 0.6rem 2.5rem 0.6rem 1rem;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  color: var(--x-ink);
  /* appearance:none removes the arrow, so one must be drawn back — a select
     with no affordance looks like a text box that refuses to accept typing. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%238C8579' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 0.75rem;
}

/* ── Product grid ──────────────────────────────────────────────────────────── */

.woocommerce ul.products {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
  clear: both;
}

/*
 * ⚠️ THE PROJECT'S BREAKPOINTS, NOT AD-HOC ONES.
 *
 *   ≤ 767px    small + large mobile
 *   768–991    tablet
 *   992–1199   small desktop
 *   ≥ 1200     desktop + large desktop
 *
 * This ladder governs every product grid that is NOT the main shop archive —
 * category archives, related products, cross-sells. The shop archive overrides
 * it from shop-all.css at `.woocommerce ul.x-sa__grid.products`, which it has to
 * do at (0,3,1): this selector is (0,2,1) and would otherwise win on specificity
 * however late the other file is enqueued.
 *
 * Two up on a phone here, deliberately — these are secondary grids beside other
 * content, where one enormous card per screen would bury what the page is for.
 */
@media (min-width: 768px) {
  .woocommerce ul.products { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; }
}
@media (min-width: 992px) {
  .woocommerce ul.products { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* WooCommerce adds first/last classes and float rules for its own layout.
   The grid ignores them, but the floats must be cleared or the last row
   collapses onto the pagination. */
.woocommerce ul.products li.product {
  float: none !important;
  width: auto !important;
  margin: 0 !important;
  display: flex;
  flex-direction: column;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  overflow: hidden;
  transition: border-color 0.2s ease, transform 0.2s ease;
}

.woocommerce ul.products li.product:hover {
  border-color: var(--x-line-strong);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .woocommerce ul.products li.product { transition: none; }
  .woocommerce ul.products li.product:hover { transform: none; }
}

.woocommerce ul.products li.product a { display: block; }

.woocommerce ul.products li.product img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--x-surface);
  margin: 0;
}

.woocommerce ul.products li.product .woocommerce-loop-product__link {
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* The card is a flex column so the actions row can be pushed to its base. */
.woocommerce ul.products li.product > .x-actions { margin-top: auto; }

.x-card__title {
  font-family: var(--font-body);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--x-ink);
  margin: 0;
  padding: 0.875rem 1rem 0;
  line-height: 1.4;
}

.x-card__rating { padding: 0.5rem 1rem 0; display: flex; align-items: center; gap: 0.375rem; }
.x-card__rating span { font-size: 0.75rem; color: var(--x-muted); }

.x-card__price {
  padding: 0.375rem 1rem 0;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--x-ink);
}

.x-price-note { font-size: 0.6875rem; font-weight: 400; color: var(--x-muted); }

.woocommerce ul.products li.product .price { color: var(--x-ink); font-size: inherit; }
.woocommerce ul.products li.product .price del { color: var(--x-muted); font-weight: 400; margin-right: 0.375rem; }
.woocommerce ul.products li.product .price ins { text-decoration: none; }

/* ── Listing actions ──────────────────────────────────────────────────────── */

.x-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin: 0.875rem 1rem 1rem;
  /* Pins the row to the bottom of the card so buttons line up across a row of
     products with different title lengths. */
  margin-top: auto;
  padding-top: 0.875rem;
}

.x-actions--single { grid-template-columns: 1fr; }

.x-actions .x-btn {
  width: 100%;
  padding-inline: 0.75rem;
  font-size: 0.75rem;
  /* Two buttons on a narrow card: let the label shrink rather than overflow. */
  min-width: 0;
  white-space: nowrap;
}

.x-actions__add,
.x-actions__buy { margin: 0; min-width: 0; }

/*
 * ⚠️ MEASURED AT 91×40 — THE TWO MOST IMPORTANT BUTTONS ON THE PAGE.
 *
 * Everything else can be a near miss; these two are the whole point of a
 * product card, they sit in a grid of other cards' buttons, and a mis-tap
 * either adds the wrong product or does nothing. 44px is the floor a thumb
 * hits reliably, and the cards have the room.
 */
.x-actions .x-btn,
.x-actions__addbtn,
.x-actions__buy {
  min-height: 2.75rem;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.x-actions__add[hidden] { display: none; }

/* Quantity stepper — occupies the same cell the Add button vacated. */
.x-qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem;
  height: 100%;
  min-height: 2.625rem;
  padding: 0.25rem;
  border-radius: var(--x-r-pill);
  background: var(--x-dark);
  color: var(--x-bg);
}

.x-qty[hidden] { display: none; }

/*
 * ⚠️ THE STEPPER TAKES THE WHOLE ROW.
 *
 * `.x-actions` is a two-column grid holding Add to Bag beside Buy Now. Once the
 * product is in the bag, Buy Now is hidden and the stepper was left sitting in
 * column one with an empty column beside it — a half-width control floating
 * against dead space, which read as a missing button rather than a deliberate
 * state.
 *
 * Spanning is safe unconditionally: the stepper is visible in exactly the same
 * state that hides Buy Now, both driven by the quantity being above zero. On
 * `.x-actions--single` there is only one column and `1 / -1` is simply it.
 */
.x-qty { grid-column: 1 / -1; }

/*
 * ⚠️ THE EXPAND IS DRIVEN BY A CLASS, NOT BY THE STEPPER BEING VISIBLE.
 *
 * `.x-qty:not([hidden])` would have been the obvious hook, and it would have
 * replayed the animation on every page load for every product already in the
 * bag — a shop grid that shudders as it arrives. The class is added by the
 * script only when the state actually flips under the shopper's hand, so a
 * server-rendered "2 in bag" is simply already open.
 *
 * ⚠️ `margin-right`, NOT `transform: scaleX()`.
 *
 * Scaling is the cheap way to animate a width, and it would have stretched the
 * −, the count and the + horizontally as it went — the control arriving
 * squashed and snapping to shape. Animating the margin reflows one small
 * element and its contents keep their proportions throughout.
 */
@keyframes x-qty-open {
  from { margin-right: calc(50% + 0.25rem); }
  to   { margin-right: 0; }
}

.x-actions.is-opening .x-qty {
  animation: x-qty-open 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Coming back the other way, the pair of buttons fades in rather than the
   stepper collapsing — the buttons are what the shopper is looking for. */
@keyframes x-actions-return {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: none; }
}

.x-actions.is-closing .x-actions__add,
.x-actions.is-closing .x-actions__buy {
  animation: x-actions-return 0.28s ease-out both;
}

.x-actions.is-closing .x-actions__buy { animation-delay: 0.04s; }

@media (prefers-reduced-motion: reduce) {
  .x-actions.is-opening .x-qty,
  .x-actions.is-closing .x-actions__add,
  .x-actions.is-closing .x-actions__buy { animation: none; }
}

.x-qty__step {
  display: flex;
  align-items: center;
  justify-content: center;
  /* ⚠️ 30×30 MEASURED. The quantity controls are pressed with a thumb, often
     repeatedly, on a card that is already small. 44px is the floor. */
  width: 2.75rem;
  height: 2.75rem;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  flex: 0 0 auto;
  border: 0;
  border-radius: var(--x-r-pill);
  background: rgba(244, 241, 234, 0.14);
  color: var(--x-bg);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.x-qty__step:hover { background: rgba(244, 241, 234, 0.26); }
.x-qty__step:focus-visible { outline: 2px solid var(--x-bg); outline-offset: 1px; }

.x-qty__label {
  display: flex;
  align-items: baseline;
  gap: 0.25rem;
  font-size: 0.6875rem;
  line-height: 1;
  min-width: 0;
}

.x-qty__n { font-size: 0.8125rem; font-weight: 600; }
.x-qty__word { opacity: 0.7; }

/* Very narrow cards cannot hold "1 in bag" beside two round buttons. */
@media (max-width: 380px) {
  .x-actions { grid-template-columns: 1fr; }
  .x-qty__word { display: none; }
}

/* In flight: dimmed and unclickable, so a double-tap cannot queue two writes
   the shopper never sees the result of. */
.x-actions.is-busy .x-qty__step,
.x-actions.is-busy .x-btn { pointer-events: none; opacity: 0.75; }

.x-actions.has-error .x-qty { background: var(--x-danger); }

.woocommerce span.onsale {
  position: absolute;
  margin: 0.75rem;
  background: var(--x-accent);
  color: var(--x-white);
  border-radius: var(--x-r-pill);
  padding: 0.25rem 0.75rem;
  font-size: 0.6875rem;
  font-weight: 600;
  min-height: 0;
  line-height: 1.4;
}

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

.woocommerce div.product .stock.out-of-stock {
  color: var(--x-danger);
  font-size: 0.8125rem;
}

/* Sits opposite the sale flash so the two never collide on one card. */
.x-stock-flag {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 2;
  padding: 0.25rem 0.625rem;
  border-radius: var(--x-r-pill);
  background: rgba(30, 29, 27, 0.82);
  color: var(--x-bg);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.5;
  /* The image is greyed rather than the card, so the product still reads as
     part of the range — just not available today. */
  backdrop-filter: blur(2px);
}

.woocommerce ul.products li.product.outofstock img {
  opacity: 0.62;
  filter: saturate(0.75);
}

.woocommerce ul.products li.product.outofstock:hover img {
  opacity: 0.72;
}

/* ── Single product ────────────────────────────────────────────────────────── */

.woocommerce div.product {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: start;
}

@media (min-width: 1024px) {
  .woocommerce div.product {
    grid-template-columns: 1.05fr 0.95fr;
    gap: 3.5rem;
  }
}

.woocommerce div.product div.images { margin: 0; width: auto; float: none; }

.woocommerce div.product div.images img {
  border-radius: var(--x-r-lg);
  background: var(--x-surface);
}

.woocommerce div.product div.summary { margin: 0; width: auto; float: none; }

.woocommerce div.product .product_title {
  font-family: var(--font-display);
  font-size: 1.875rem;
  line-height: 1.15;
  margin: 0 0 0.75rem;
}
@media (min-width: 1024px) {
  .woocommerce div.product .product_title { font-size: 2.5rem; }
}

.woocommerce div.product p.price,
.woocommerce div.product span.price {
  color: var(--x-ink);
  font-size: 1.375rem;
  font-weight: 600;
  margin: 0 0 1rem;
}

.woocommerce div.product p.price del { color: var(--x-muted); font-weight: 400; font-size: 1rem; }
.woocommerce div.product p.price ins { text-decoration: none; }

.woocommerce div.product .woocommerce-product-details__short-description {
  color: var(--x-ink-soft);
  font-size: 0.9375rem;
  line-height: 1.7;
  margin-bottom: 1.5rem;
}

.woocommerce div.product form.cart {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin: 1.5rem 0;
}

.woocommerce div.product form.cart .button { flex: 1 1 12rem; }

.woocommerce .quantity input.qty {
  width: 4.5rem;
  height: 3rem;
  text-align: center;
  border: 1px solid var(--x-line);
  background: var(--x-field);
  border-radius: var(--x-r-md);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  color: var(--x-ink);
}

.woocommerce div.product .product_meta {
  font-size: 0.8125rem;
  color: var(--x-muted);
  border-top: 1px solid var(--x-line);
  padding-top: 1.25rem;
  display: grid;
  gap: 0.375rem;
}

/* Tabs */
.woocommerce div.product .woocommerce-tabs {
  grid-column: 1 / -1;
  margin-top: 2rem;
  border-top: 1px solid var(--x-line);
  padding-top: 2rem;
}

.woocommerce div.product .woocommerce-tabs ul.tabs {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--x-line);
}

.woocommerce div.product .woocommerce-tabs ul.tabs::before,
.woocommerce div.product .woocommerce-tabs ul.tabs li::before,
.woocommerce div.product .woocommerce-tabs ul.tabs li::after { display: none; }

.woocommerce div.product .woocommerce-tabs ul.tabs li {
  margin: 0; padding: 0; background: none; border: 0; border-radius: 0;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li a {
  display: block;
  /* ⚠️ MEASURED AT 36px. These are real controls — they switch the panel
     below — so the text-block exemption does not apply to them. The extra
     padding is on top, keeping the underline where the design puts it. */
  padding: 0.65rem 0 0.75rem;
  min-height: 2.75rem;
  box-sizing: border-box;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--x-muted);
  border-bottom: 2px solid transparent;
  touch-action: manipulation;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li.active a {
  color: var(--x-ink);
  border-bottom-color: var(--x-dark);
}

.woocommerce div.product .woocommerce-tabs .panel h2 { font-size: 1.25rem; margin-bottom: 0.75rem; }
.woocommerce div.product .woocommerce-tabs .panel { color: var(--x-ink-soft); line-height: 1.7; }

/* Related products */
.woocommerce .related, .woocommerce .upsells {
  grid-column: 1 / -1;
  margin-top: 3rem;
  border-top: 1px solid var(--x-line);
  padding-top: 2.5rem;
}
.woocommerce .related > h2, .woocommerce .upsells > h2 {
  font-family: var(--font-display);
  font-size: 1.5rem;
  margin-bottom: 1.5rem;
}

/* ── Cart ──────────────────────────────────────────────────────────────────── */

.woocommerce table.shop_table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  overflow: hidden;
  background: var(--x-white);
  margin-bottom: 1.5rem;
}

.woocommerce table.shop_table th {
  text-align: left;
  padding: 1rem;
  font-family: var(--font-body);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--x-muted);
  border-bottom: 1px solid var(--x-line);
  background: var(--x-bg-alt);
}

.woocommerce table.shop_table td {
  padding: 1rem;
  border-bottom: 1px solid var(--x-line);
  vertical-align: middle;
  font-size: 0.875rem;
}

.woocommerce table.shop_table tr:last-child td { border-bottom: 0; }

.woocommerce table.cart img { width: 4rem; border-radius: var(--x-r-md); }

.woocommerce a.remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem; height: 1.75rem;
  border-radius: var(--x-r-pill);
  color: var(--x-muted);
  font-size: 1.125rem;
  line-height: 1;
  text-decoration: none;
}
.woocommerce a.remove:hover { background: var(--x-surface); color: var(--x-danger); }

.woocommerce .cart_totals h2,
.woocommerce-checkout h3 {
  font-family: var(--font-display);
  font-size: 1.375rem;
  margin-bottom: 1rem;
}

/*
 * ⚠️ THE OLD CART LAYOUT LIVED HERE, AND IT BROKE THE NEW ONE.
 *
 * This block turned `.woocommerce` into a two-column grid whenever the page
 * contained `.cart-collaterals`, which was right when the cart was a WooCommerce
 * table with the totals floated beside it. `cart/cart.php` now owns the layout
 * through `.x-cart` — but the `:has(.cart-collaterals)` selector still matched,
 * so `.woocommerce` stayed a grid, the notices took the first column and the
 * entire cart was squeezed into the second: a 0px-wide item list beside a
 * 352px summary, with the two overlapping.
 *
 * The lesson is in the selector, not the widths: `:has()` on a structural class
 * keeps matching long after the structure it described has been replaced, and
 * it fails silently and at a distance. Layout for the cart belongs in `.x-cart`
 * and nowhere else.
 */

.woocommerce .coupon { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1rem; }

/*
 * ⚠️ CART TABLES MUST COLLAPSE ON A PHONE.
 * WooCommerce's own small-screen stylesheet is dequeued, so without this a
 * six-column cart table forces horizontal scrolling and the remove button ends
 * up off screen.
 */
@media (max-width: 767px) {
  .woocommerce table.shop_table thead { display: none; }
  .woocommerce table.shop_table tr { display: grid; grid-template-columns: 1fr; padding: 0.75rem; border-bottom: 1px solid var(--x-line); }
  .woocommerce table.shop_table td { display: flex; justify-content: space-between; align-items: center; gap: 1rem; border: 0; padding: 0.375rem 0; }
  .woocommerce table.shop_table td::before { content: attr(data-title); font-size: 0.75rem; color: var(--x-muted); }
  .woocommerce table.shop_table td.product-remove::before { content: none; }
}

/* ── Forms ─────────────────────────────────────────────────────────────────── */

.woocommerce form .form-row { display: flex; flex-direction: column; gap: 0.5rem; margin: 0 0 1rem; padding: 0; }

.woocommerce form .form-row label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--x-ink-soft);
}

.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce .select2-container .select2-selection--single {
  width: 100%;
  border: 1px solid var(--x-line);
  background: var(--x-field);
  border-radius: var(--x-r-md);
  padding: 0.75rem 1rem;
  font-family: var(--font-body);
  font-size: 0.875rem;
  color: var(--x-ink);
  height: auto;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row textarea:focus,
.woocommerce form .form-row select:focus {
  outline: none;
  border-color: var(--x-dark);
  background: var(--x-white);
}

.woocommerce form .form-row.woocommerce-invalid input.input-text {
  border-color: #c87a6c;
  background: #fbf0ed;
}

/*
 * ⚠️ THIS IS A BARE <p>, SO IT ARRIVES WITH A PARAGRAPH'S MARGINS.
 *
 * WooCommerce's checkout.js builds the inline error as
 * `document.createElement('p')` and appends it to the `.form-row`
 * (checkout.js ~1121). Unstyled, it inherits the body font size and a 1em
 * margin top and bottom — so the message rendered at full body size, a clear
 * line-and-a-half below the field it belonged to, reading as a new sentence
 * about the page rather than a fault on that input.
 *
 * Tight to the field, small, and red: the red is what makes it an error at a
 * glance, and the proximity is what tells you WHICH field. Both matter — the
 * field's own border also turns terracotta, but that tint is deliberately soft
 * and cannot carry the message on its own.
 *
 * #9a2f2f rather than the border's #c87a6c: this is text and has to stay
 * legible (about 6.6:1 on the card), whereas the border is decoration.
 * It matches the coupon box's error colour, so errors look the same everywhere
 * on this page.
 *
 * ⚠️ 13px IS THE FLOOR, NOT A STARTING POINT — DO NOT SHRINK THIS FURTHER.
 *
 * mobile.css sets 13px as the minimum for anything functional, and a validation
 * message is the most functional text on the page: it is the instruction that
 * unblocks the order. Small enough to read as an annotation on the field,
 * never small enough to squint at.
 */
.checkout-inline-error-message {
  margin: 0.25rem 0 0;
  font-size: 0.8125rem;
  line-height: 1.4;
  font-weight: 500;
  color: #9a2f2f;
}

/*
 * ⚠️ 24px OF PHANTOM SPACE UNDER EVERY INPUT.
 *
 * `.woocommerce-input-wrapper` is a `<span>` holding one input, with no padding
 * and no margin — and it measured 24px TALLER than the input inside it. The
 * input is inline-level, so the wrapper establishes a line box and reserves
 * descender space beneath it for text that will never be there.
 *
 * Invisible while nothing followed the input. It became obvious once the
 * validation message moved up beneath it: 24px of that "gap" was not spacing
 * anyone had chosen, and no amount of tuning the message's own margin could
 * close it.
 *
 * A flex container has no line boxes, so the wrapper collapses onto its input.
 */
.woocommerce form .form-row > .woocommerce-input-wrapper {
  display: flex;
  flex-direction: column;
}

/*
 * ⚠️ THE PHONE ROW IS THE ONE PLACE "APPEND" IS NOT GOOD ENOUGH.
 *
 * checkout.js appends the message to the END of the `.form-row`. For every
 * other field that is directly under the input. The phone row also holds the
 * OTP controls and a description, in this DOM order:
 *
 *     label -> .woocommerce-input-wrapper -> .xl-otp-row -> .description
 *                                                        -> [error appended here]
 *
 * so the error rendered below the "Verify phone" button AND the helper text —
 * measured at 100px from the input it describes, on the first and most
 * important field on the page.
 *
 * Reordering with flex fixes the position without touching WooCommerce's JS or
 * the DOM, so nothing downstream (aria-describedby, the removal on re-validate)
 * has to know. Scoped to these two rows only: every other field is already
 * correct by appending, and making all `.form-row`s flex would be a much wider
 * change than the problem justifies.
 */
#billing_phone_field,
#shipping_phone_field {
  display: flex;
  flex-direction: column;
}
#billing_phone_field > label,
#shipping_phone_field > label { order: 1; }

#billing_phone_field > .woocommerce-input-wrapper,
#shipping_phone_field > .woocommerce-input-wrapper { order: 2; }

#billing_phone_field > .checkout-inline-error-message,
#shipping_phone_field > .checkout-inline-error-message { order: 3; }

#billing_phone_field > .xl-otp-row,
#shipping_phone_field > .xl-otp-row { order: 4; }

#billing_phone_field > .description,
#shipping_phone_field > .description { order: 5; }

.woocommerce .woocommerce-message,
.woocommerce .woocommerce-info,
.woocommerce .woocommerce-error {
  border: 1px solid var(--x-line);
  background: var(--x-bg-alt);
  border-radius: var(--x-r-md);
  padding: 1rem 1.25rem;
  margin: 0 0 1.5rem;
  list-style: none;
  color: var(--x-ink);
  font-size: 0.875rem;
}

.woocommerce .woocommerce-error { border-color: #e3c4be; background: #fbf0ed; color: #8a3b2e; }
.woocommerce .woocommerce-message::before,
.woocommerce .woocommerce-info::before,
.woocommerce .woocommerce-error::before { content: none; }

/* ── Pagination ────────────────────────────────────────────────────────────── */

.woocommerce nav.woocommerce-pagination ul {
  display: flex;
  gap: 0.5rem;
  list-style: none;
  padding: 0;
  margin: 2.5rem 0 0;
  border: 0;
  justify-content: center;
}

.woocommerce nav.woocommerce-pagination ul li { border: 0; margin: 0; overflow: visible; }

.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 2.5rem;
  height: 2.5rem;
  padding: 0 0.5rem;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-pill);
  font-size: 0.875rem;
  color: var(--x-ink);
  background: var(--x-white);
}

.woocommerce nav.woocommerce-pagination ul li span.current {
  background: var(--x-dark);
  border-color: var(--x-dark);
  color: var(--x-bg);
}

/* ── Content pages ─────────────────────────────────────────────────────────── */

.x-page { padding-block: 3rem 4rem; }
.x-page__title { font-size: 2rem; line-height: 1.15; margin-bottom: 1.5rem; }
@media (min-width: 1024px) { .x-page__title { font-size: 2.75rem; } }

.x-prose { max-width: 45rem; color: var(--x-ink-soft); line-height: 1.8; }
.x-prose h2 { font-size: 1.5rem; margin: 2rem 0 0.75rem; color: var(--x-ink); }
.x-prose h3 { font-size: 1.25rem; margin: 1.5rem 0 0.5rem; color: var(--x-ink); }
.x-prose a { color: var(--x-accent); text-decoration: underline; text-underline-offset: 2px; }
.x-prose img { border-radius: var(--x-r-lg); margin-block: 1.5rem; }

/* ── Star ratings ──────────────────────────────────────────────────────────────
 *
 * ⚠️ REBUILT, NOT INHERITED. WooCommerce draws stars with an @font-face icon
 * font declared inside `woocommerce-general` — which this theme dequeues. Left
 * alone, every rating renders as its own accessible fallback text: literally
 * "1 of 5 stars 2 of 5 stars 3 of 5 stars…" across the page. The text stays in
 * the markup for screen readers; it is only hidden visually.
 */

.woocommerce .star-rating {
  position: relative;
  display: inline-block;
  width: 5.6em;
  height: 1.3em;
  overflow: hidden;
  font-size: 0.8125rem;
  line-height: 1.3;
  font-family: var(--font-body);
}

.woocommerce .star-rating::before {
  content: "★★★★★";
  position: absolute;
  inset: 0;
  color: var(--x-line-strong);
  letter-spacing: 0.12em;
}

.woocommerce .star-rating span {
  position: absolute;
  inset: 0 auto 0 0;
  overflow: hidden;
  /* Pushes WooCommerce's "Rated 4 out of 5" text out of the visible box while
     leaving it in the accessibility tree. */
  padding-top: 2em;
}

.woocommerce .star-rating span::before {
  content: "★★★★★";
  position: absolute;
  top: 0;
  left: 0;
  color: var(--x-accent);
  letter-spacing: 0.12em;
}

/* The rating input on the review form. */
.woocommerce #review_form p.stars { margin: 0 0 1rem; }
.woocommerce #review_form p.stars span { display: inline-flex; gap: 0.25rem; }

.woocommerce #review_form p.stars a {
  position: relative;
  display: block;
  width: 1.5rem;
  height: 1.5rem;
  text-indent: -9999px;
  overflow: hidden;
}

.woocommerce #review_form p.stars a::before {
  content: "★";
  position: absolute;
  inset: 0;
  text-indent: 0;
  font-size: 1.25rem;
  line-height: 1.2;
  color: var(--x-line-strong);
  transition: color 0.15s ease;
}

.woocommerce #review_form p.stars a:hover::before,
.woocommerce #review_form p.stars.selected a.active::before,
.woocommerce #review_form p.stars.selected a:not(.active)::before { color: var(--x-accent); }

.woocommerce #review_form p.stars.selected a.active ~ a::before { color: var(--x-line-strong); }

/* ── Reviews ───────────────────────────────────────────────────────────────── */

.woocommerce #reviews #comments h2 { font-size: 1.25rem; margin-bottom: 1rem; }
.woocommerce #reviews .commentlist { list-style: none; padding: 0; margin: 0 0 2rem; display: grid; gap: 1rem; }

.woocommerce #reviews .commentlist li {
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: 1.25rem;
  background: var(--x-white);
}

.woocommerce #reviews .comment-text p { margin: 0.5rem 0 0; color: var(--x-ink-soft); }
.woocommerce #reviews .meta { font-size: 0.8125rem; color: var(--x-muted); }

/*
 * The review form is a WordPress comment form, not a WooCommerce form, so it
 * carries none of the `.form-row` classes styled above — without this its
 * inputs render as raw browser defaults in the middle of a designed page.
 */
.woocommerce #review_form .comment-form { display: grid; gap: 1rem; max-width: 34rem; }
.woocommerce #review_form .comment-form p { margin: 0; display: grid; gap: 0.5rem; }

.woocommerce #review_form .comment-form label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--x-ink-soft);
}

.woocommerce #review_form .comment-form input[type="text"],
.woocommerce #review_form .comment-form input[type="email"],
.woocommerce #review_form .comment-form textarea {
  width: 100%;
  border: 1px solid var(--x-line);
  background: var(--x-field);
  border-radius: var(--x-r-md);
  padding: 0.75rem 1rem;
  font-family: var(--font-body);
  font-size: 0.875rem;
  color: var(--x-ink);
}

.woocommerce #review_form .comment-form input:focus,
.woocommerce #review_form .comment-form textarea:focus {
  outline: none;
  border-color: var(--x-dark);
  background: var(--x-white);
}

.woocommerce #review_form .comment-form-cookies-consent {
  grid-template-columns: auto 1fr;
  align-items: center;
}
.woocommerce #review_form .comment-form-cookies-consent label { font-weight: 400; font-size: 0.75rem; }

.woocommerce #review_form .form-submit { margin: 0; justify-self: start; }
.woocommerce #review_form .form-submit input { width: auto; }

.woocommerce #reviews .woocommerce-noreviews { color: var(--x-ink-soft); }

/* ── Empty cart ────────────────────────────────────────────────────────────── */

/*
 * ⚠️ SIZED WITH clamp(), NOT BREAKPOINTS.
 *
 * This page is one centred column, so every dimension can scale continuously
 * with the viewport instead of snapping at 768 and 1024. Breakpoints left the
 * 1.875rem title unchanged from 390px all the way to 1023px, where it looked
 * lost, then jumped. The `vw` middle term does the work; the two ends stop it
 * becoming unreadable on a phone or absurd on a 27" display.
 */

.x-empty {
  /* Without this the panel stretches the full 75rem container and the design
     dissolves into a very wide, very empty band on a large monitor. */
  max-width: 62rem;
  margin-inline: auto;
  padding-block: clamp(1rem, 3vw, 2.5rem) clamp(2rem, 5vw, 4rem);
}

.x-empty__panel {
  background:
    linear-gradient(135deg, #f8f6f2 0%, #f3efea 45%, #f8ece7 100%);
  /* ⚠️ THE BORDER IS DOING THE WORK, NOT THE GRADIENT. On a large screen the
     wash alone was invisible against the cream page — the panel read as loose
     text with no edge. A hairline gives it a shape; the gradient only gives it
     warmth. */
  border: 1px solid var(--x-line);
  border-radius: clamp(1.25rem, 2.5vw, 2rem);
  padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.25rem, 4vw, 3.5rem);
  text-align: center;
}

.x-empty__mark {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(3.5rem, 7vw, 4.75rem);
  height: clamp(3.5rem, 7vw, 4.75rem);
  border-radius: var(--x-r-pill);
  background: var(--x-white);
  border: 1px solid var(--x-line);
  color: var(--x-ink);
  margin-bottom: clamp(1.25rem, 3vw, 1.75rem);
}

.x-empty__mark svg { width: 45%; height: 45%; }

.x-empty__sparkle {
  position: absolute;
  top: -0.35rem;
  right: -0.5rem;
  width: 1.125rem;
  height: 1.125rem;
  color: var(--x-accent);
}

.x-empty__eyebrow {
  margin: 0 0 clamp(0.5rem, 1.5vw, 0.875rem);
  font-size: clamp(0.625rem, 1vw, 0.6875rem);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--x-accent);
}

.x-empty__title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 5vw, 3rem);
  line-height: 1.1;
  margin: 0 0 clamp(0.75rem, 2vw, 1.125rem);
}

.x-empty__copy {
  /* Measured in characters, so the line length stays readable at any size
     rather than growing with the panel. */
  max-width: 46ch;
  margin: 0 auto;
  color: var(--x-ink-soft);
  font-size: clamp(0.875rem, 1.15vw, 1rem);
  line-height: 1.7;
}

.x-empty__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: clamp(1.5rem, 3.5vw, 2.25rem);
}

/* Below ~26rem two pills wrap into a ragged pair that reads as a mistake. */
@media (max-width: 26rem) {
  .x-empty__actions { flex-direction: column; }
  .x-empty__actions .x-btn { width: 100%; }
  /* "CONTINUE SHOPPING" broke onto two lines inside the pill at 320px. The
     tracking and horizontal padding are what pushed it over, not the text. */
  .x-empty__actions .x-btn {
    padding-inline: 1.25rem;
    letter-spacing: 0.03em;
    font-size: 0.6875rem;
  }
}

.x-btn--accent {
  background: var(--x-accent);
  color: var(--x-white);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 0.75rem;
}
.x-btn--accent:hover { background: var(--x-accent-hover); color: var(--x-white); }

.x-empty__actions .x-btn--ghost {
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 0.75rem;
  background: var(--x-white);
}

.x-empty__jump {
  margin: clamp(2rem, 4vw, 3rem) 0 clamp(0.875rem, 2vw, 1.25rem);
  text-align: center;
  font-size: clamp(0.625rem, 1vw, 0.6875rem);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--x-muted);
}

.x-empty__cards {
  display: grid;
  /* `min(100%, …)` keeps a single card from overflowing at 320px, which a bare
     minmax() floor does not. auto-fit closes the row up when a destination is
     missing, rather than leaving a hole. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9.5rem), 1fr));
  gap: clamp(0.625rem, 1.5vw, 1rem);
  max-width: 46rem;
  margin-inline: auto;
}

.x-empty__cards a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  padding: clamp(1.125rem, 2.5vw, 1.625rem) 1rem;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  transition: border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

.x-empty__cards a:hover {
  border-color: var(--x-line-strong);
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(30, 29, 27, 0.05);
}

.x-empty__cardicon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--x-r-md);
  background: var(--x-surface);
  color: var(--x-ink);
}

.x-empty__cardlabel {
  font-size: clamp(0.75rem, 1.05vw, 0.8125rem);
  font-weight: 500;
  color: var(--x-ink);
  text-align: center;
}

/* ── Empty cart: motion ────────────────────────────────────────────────────────
 *
 * ⚠️ EVERY ANIMATION HERE RESTS IN THE VISIBLE STATE AND PLAYS FORWARD ONLY.
 * These are pure CSS keyframes with `both` fill, so if anything goes wrong the
 * content is still on screen — nothing is hidden waiting for JavaScript that
 * might never run. The pointer sheen below is the only scripted part, and it is
 * decoration layered on top of an already-complete page.
 */

@keyframes x-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes x-pop {
  0%   { opacity: 0; transform: scale(0.8); }
  70%  { transform: scale(1.06); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes x-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}

@keyframes x-twinkle {
  0%, 100% { opacity: 0.4; transform: scale(0.8) rotate(0deg); }
  50%      { opacity: 1;   transform: scale(1.15) rotate(20deg); }
}

/* A very slow wash across the panel — enough to feel alive, not enough to
   notice while reading. */
@keyframes x-drift {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

.x-empty__panel {
  position: relative;
  overflow: hidden;
  background-size: 200% 200%;
  animation: x-drift 22s ease-in-out infinite;
}

/* Pointer-follow sheen. Sits behind the content and never intercepts clicks. */
.x-empty__panel::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(
    20rem 20rem at var(--x-mx, 50%) var(--x-my, 50%),
    rgba(201, 105, 74, 0.13),
    transparent 70%
  );
  opacity: 0;
  transition: opacity 0.35s ease;
}

.x-empty__panel.is-live::before { opacity: 1; }

.x-empty__panel > * { position: relative; z-index: 1; }

.x-empty__mark {
  animation:
    x-pop 0.55s cubic-bezier(0.22, 1, 0.36, 1) both,
    x-float 4.5s ease-in-out 0.7s infinite;
}

/* Position and size live in the base rule; this only adds the movement. */
.x-empty__sparkle { animation: x-twinkle 3s ease-in-out 0.9s infinite; }

/* Staggered entrance — the order a reader takes them in. */
.x-empty__eyebrow { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.10s both; }
.x-empty__title   { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.18s both; }
.x-empty__copy    { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.26s both; }
.x-empty__actions { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.34s both; }
.x-empty__jump    { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.42s both; }

.x-empty__cards a { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; }
.x-empty__cards a:hover .x-empty__cardicon { background: var(--x-dark); color: var(--x-bg); transform: translateY(-3px) scale(1.06); }
.x-empty__cards a:nth-child(1) { animation-delay: 0.48s; }
.x-empty__cards a:nth-child(2) { animation-delay: 0.54s; }
.x-empty__cards a:nth-child(3) { animation-delay: 0.60s; }
.x-empty__cards a:nth-child(4) { animation-delay: 0.66s; }

/* Buttons: lift, and nudge the icon in the direction of travel. */
.x-empty__actions .x-btn svg { transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1); }
.x-empty__actions .x-btn:hover svg { transform: translateX(3px); }
.x-empty__actions .x-btn--ghost:hover svg { transform: scale(1.15); }

.x-btn--accent {
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
  transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
.x-btn--accent:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(201, 105, 74, 0.28);
}
.x-btn--accent:active { transform: translateY(0); }

/* Shortcut cards: the icon tile is what reacts, so the card itself stays calm. */
.x-empty__cardicon {
  transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
.x-empty__cards a:hover .x-empty__cardicon {
  background: var(--x-dark);
  color: var(--x-bg);
  transform: translateY(-3px) scale(1.06);
}
.x-empty__cards a:focus-visible {
  outline: 2px solid var(--x-dark);
  outline-offset: 3px;
}

/**
 * ⚠️ EVERYTHING STOPS UNDER REDUCED MOTION.
 *
 * A floating, drifting, sheening panel is exactly the kind of ambient movement
 * that triggers vestibular symptoms. The content is identical either way — only
 * the movement goes.
 */
@media (prefers-reduced-motion: reduce) {
  .x-empty__panel,
  .x-empty__mark,
  .x-empty__sparkle,
  .x-empty__eyebrow,
  .x-empty__title,
  .x-empty__copy,
  .x-empty__actions,
  .x-empty__jump,
  .x-empty__cards a {
    animation: none !important;
  }
  .x-empty__panel::before { display: none; }
  .x-empty__actions .x-btn svg,
  .x-empty__cardicon,
  .x-btn--accent { transition: none; }
  .x-btn--accent:hover,
  .x-empty__cards a:hover .x-empty__cardicon { transform: none; }
}


/* ── Shared page hero ─────────────────────────────────────────────────────────
 *
 * ⚠️ ONE PATTERN, ONE SET OF NUMBERS.
 *
 * Contact, Track order and About each grew their own hero with its own padding,
 * type scale, divider and overlap — 64px on one page, 40px on another, a rule
 * here and a plus there. Nobody notices any single value, but moving between
 * the pages feels like moving between sites. These tokens are the whole
 * definition; the pages only opt in.
 */
:root {
  --x-hero-top: clamp(2.5rem, 6vw, 4.5rem);
  --x-hero-bottom: clamp(4.5rem, 9vw, 7.5rem);
  /* The lift is applied only from `small` up — at phone widths there is no side
     gutter for the seam to show in, so it would just eat the band. */
  --x-hero-overlap: 4rem;   /* 64px */
}

.x-hero {
  position: relative;
  overflow: hidden;
  background: var(--x-bg-alt);
  border-bottom: 1px solid var(--x-line);
  text-align: center;
  padding-block: var(--x-hero-top) var(--x-hero-bottom);
}

.x-hero > .x-container { position: relative; z-index: 1; }

.x-hero__eyebrow {
  margin: 0 0 0.75rem;
  font-size: clamp(0.625rem, 1vw, 0.6875rem);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--x-accent);
}

.x-hero__title {
  font-family: var(--font-display);
  font-size: clamp(1.875rem, 5vw, 3.5rem);
  line-height: 1.1;
  margin: 0;
}

/* The same mark on every hero — a quiet brand signature rather than three
   different dividers. */
.x-hero__mark {
  display: block;
  margin: 0.75rem auto 0;
  color: var(--x-accent);
  font-size: 1rem;
  line-height: 1;
}

.x-hero__intro {
  max-width: 48ch;
  margin: clamp(0.75rem, 2vw, 1.125rem) auto 0;
  color: var(--x-ink-soft);
  font-size: clamp(0.875rem, 1.15vw, 0.9375rem);
  line-height: 1.7;
}

/* Panels that ride up over the band's bottom edge. */
.x-overlap { position: relative; z-index: 1; }

@media (min-width: 1024px) {
  .x-overlap { margin-top: calc(var(--x-hero-overlap) * -1); }
}

.x-hero__eyebrow { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.05s both; }
.x-hero__title   { animation: x-rise 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.12s both; }
.x-hero__mark    { animation: x-rise 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.20s both; }
.x-hero__intro   { animation: x-rise 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.26s both; }

@media (prefers-reduced-motion: reduce) {
  .x-hero__eyebrow, .x-hero__title, .x-hero__mark, .x-hero__intro { animation: none !important; }
}

/* ── Contact page ─────────────────────────────────────────────────────────── */






.x-contact { padding-block: clamp(2rem, 5vw, 3rem) clamp(3rem, 6vw, 5rem); }

.x-contact__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

@media (min-width: 1024px) {
  .x-contact__grid { grid-template-columns: 1.15fr 0.85fr; gap: 1.5rem; align-items: start; }
}

.x-contact__panel {
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: clamp(1.25rem, 2vw, 1.75rem);
  padding: clamp(1.25rem, 3.5vw, 2.25rem);
}

.x-contact__formtitle { font-size: clamp(1.25rem, 2.5vw, 1.625rem); line-height: 1.2; margin: 0; }
.x-contact__formnote { margin: 0.5rem 0 0; max-width: 34rem; color: var(--x-ink-soft); font-size: 0.875rem; line-height: 1.6; }
.x-contact__formtitle + .x-cform, .x-contact__formnote + .x-cform { margin-top: 1.5rem; }

/* ── Form ─────────────────────────────────────────────────────────────────── */

.x-cform__grid { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 512px) { .x-cform__grid { grid-template-columns: 1fr 1fr; } }

.x-cform__field { display: grid; gap: 0.5rem; }
.x-cform__field.is-full { grid-column: 1 / -1; }

.x-cform__label { font-size: 0.8125rem; font-weight: 500; color: var(--x-ink-soft); }
.x-cform__optional { color: #b4ab9c; font-weight: 400; }

.x-cform__input {
  width: 100%;
  border: 1px solid var(--x-line);
  background: var(--x-field);
  border-radius: var(--x-r-md);
  padding: 0.75rem 1rem;
  font-family: var(--font-body);
  font-size: 0.875rem;
  color: var(--x-ink);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.x-cform__input:focus { outline: none; border-color: var(--x-dark); background: var(--x-white); }

select.x-cform__input {
  appearance: none;
  padding-right: 2.75rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%238C8579' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 0.75rem;
}

textarea.x-cform__input { resize: vertical; min-height: 8rem; }

.x-cform__field.is-invalid .x-cform__input { border-color: #c87a6c; background: #fbf0ed; }
.x-cform__error { font-size: 0.75rem; color: var(--x-danger); }
.x-cform__error:empty { display: none; }

.x-cform__trap { display: none; }

.x-cform__alert {
  margin-top: 1rem;
  border: 1px solid #e3c4be;
  background: #fbf0ed;
  color: #8a3b2e;
  border-radius: var(--x-r-md);
  padding: 0.875rem 1rem;
  font-size: 0.8125rem;
  line-height: 1.6;
}

.x-cform__submit { margin-top: 1.25rem; width: 100%; }
@media (min-width: 512px) { .x-cform__submit { width: auto; } }

.x-cform__done {
  border: 1px solid var(--x-line);
  background: var(--x-surface-warm);
  border-radius: var(--x-r-lg);
  padding: clamp(2rem, 5vw, 3rem) 1.5rem;
  text-align: center;
}

.x-cform__tick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--x-r-pill);
  background: var(--x-dark);
  color: var(--x-bg);
}

.x-cform__donetitle { font-family: var(--font-display); font-size: 1.5rem; margin: 1.25rem 0 0.5rem; }
.x-cform__donebody { max-width: 34ch; margin: 0 auto; color: var(--x-ink-soft); font-size: 0.875rem; line-height: 1.7; }

/* ── Channels ─────────────────────────────────────────────────────────────── */

.x-contact__side { display: grid; gap: 0.75rem; align-content: start; }

.x-contact__card,
.x-contact__quiet {
  display: block;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: 1.125rem;
}

.x-contact__card { background: var(--x-white); display: flex; gap: 0.875rem; transition: border-color 0.2s ease, transform 0.2s ease; }
.x-contact__card:hover { border-color: var(--x-dark); transform: translateY(-2px); }
.x-contact__quiet { background: var(--x-bg-alt); }

.x-contact__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.375rem;
  height: 2.375rem;
  flex: 0 0 auto;
  border-radius: var(--x-r-pill);
  background: var(--x-surface-warm);
  color: #3a362e;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.x-contact__card:hover .x-contact__icon { background: var(--x-dark); color: var(--x-bg); }
.x-contact__icon.is-plain { background: var(--x-bg); }

.x-contact__cardbody { display: grid; gap: 0.125rem; min-width: 0; }
.x-contact__cardlabel { font-size: 0.5625rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--x-muted); }
.x-contact__cardvalue { font-size: 0.9375rem; font-weight: 500; word-break: break-word; }
.x-contact__cardnote { font-size: 0.75rem; line-height: 1.5; color: var(--x-muted); }

.x-contact__row { display: flex; gap: 0.875rem; }
.x-contact__hr { border: 0; border-top: 1px solid #dcd4c6; margin: 1rem 0; }
.x-contact__hours { list-style: none; margin: 0.25rem 0 0; padding: 0; font-size: 0.875rem; color: var(--x-ink-soft); }
.x-contact__address { font-style: normal; margin-top: 0.25rem; font-size: 0.875rem; line-height: 1.6; color: var(--x-ink-soft); }
.x-contact__address span { display: block; }
.x-contact__media { margin: 0; padding: 0 0.25rem; font-size: 0.8125rem; color: var(--x-ink-soft); }
.x-contact__media a { text-decoration: underline; text-underline-offset: 2px; }

.x-contact__map { margin-top: 1.5rem; border: 1px solid var(--x-line); border-radius: var(--x-r-lg); overflow: hidden; }
.x-contact__map iframe { display: block; width: 100%; height: clamp(16rem, 30vw, 22rem); border: 0; }

/* ── Legal ────────────────────────────────────────────────────────────────── */

.x-contact__legal {
  margin-top: 1.5rem;
  border: 1px solid var(--x-line);
  background: var(--x-bg-alt);
  border-radius: clamp(1.25rem, 2vw, 1.75rem);
  padding: clamp(1.25rem, 3.5vw, 2.5rem);
}

.x-contact__legalgrid { display: grid; grid-template-columns: 1fr; gap: 2rem; }
@media (min-width: 768px) { .x-contact__legalgrid { grid-template-columns: 1fr 1fr; gap: 3rem; } }

.x-contact__legal h2 { font-size: 1.125rem; margin: 0 0 1rem; }
.x-contact__legal dl { margin: 0; display: grid; gap: 0.75rem; }
.x-contact__legal dl > div { border-top: 1px solid #dcd4c6; padding-top: 0.625rem; }
.x-contact__legal dt { font-size: 0.5625rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--x-muted); }
.x-contact__legal dd { margin: 0.25rem 0 0; font-size: 0.8125rem; color: #3a362e; word-break: break-word; }
.x-contact__note { margin: 1rem 0 0; max-width: 34rem; font-size: 0.75rem; line-height: 1.6; color: var(--x-muted); }

@media (prefers-reduced-motion: reduce) {
  .x-contact__card { transition: none; }
  .x-contact__card:hover { transform: none; }
}

/* ── Contact: overlap + motion ────────────────────────────────────────────── */

/*
 * The panels lift over the band's bottom edge so the join reads as one
 * composition rather than two stacked blocks.
 *
 * ⚠️ DESKTOP ONLY. At phone widths there is no side gutter for the seam to show
 * in, so the lift would simply eat into the band and crop the intro copy.
 */
.x-contact { padding-top: 0; }

/*
 * ⚠️ EVERY REVEAL RESTS VISIBLE AND PLAYS FORWARD ONLY.
 * Pure CSS keyframes with `both` fill, triggered on load — not on scroll. A
 * `whileInView`-style reveal left the contact sidebar invisible on phones when
 * the observer failed, which is how a phone number and an address disappear.
 * Nothing here can hide content.
 */

.x-contact__panel   { animation: x-rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.30s both; }

.x-contact__side > * { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; }
.x-contact__side > *:nth-child(1) { animation-delay: 0.38s; }
.x-contact__side > *:nth-child(2) { animation-delay: 0.44s; }
.x-contact__side > *:nth-child(3) { animation-delay: 0.50s; }
.x-contact__side > *:nth-child(4) { animation-delay: 0.56s; }

.x-contact__map,
.x-contact__legal { animation: x-rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.62s both; }

/* Focus and hover polish on the form itself. */
.x-cform__input:focus { box-shadow: 0 0 0 3px rgba(30, 29, 27, 0.06); }
.x-cform__input:hover:not(:focus) { border-color: var(--x-line-strong); }

.x-cform__submit {
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.2s ease, box-shadow 0.2s ease;
}
.x-cform__submit:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(30, 29, 27, 0.14);
}
.x-cform__submit:active { transform: translateY(0); }
.x-cform__submit:disabled { transform: none; box-shadow: none; }

/* The alert slides in rather than appearing, so a reader notices it arrived. */
.x-cform__alert { animation: x-rise 0.25s ease-out both; }

/* Success: the tick lands with a little weight — confirmation, not decoration. */
.x-cform__done { animation: x-pop 0.45s cubic-bezier(0.22, 1, 0.36, 1) both; }
.x-cform__tick { animation: x-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 0.12s both; }

@media (prefers-reduced-motion: reduce) {
  .x-contact__eyebrow,
  .x-contact__title,
  .x-contact__intro,
  .x-contact__rule,
  .x-contact__panel,
  .x-contact__side > *,
  .x-contact__map,
  .x-contact__legal,
  .x-cform__alert,
  .x-cform__done,
  .x-cform__tick { animation: none !important; }

  .x-cform__submit { transition: none; }
  .x-cform__submit:hover { transform: none; box-shadow: none; }
}

/* ── Contact: interactions ────────────────────────────────────────────────── */



.x-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(22rem 22rem at var(--x-mx, 50%) var(--x-my, 50%), rgba(201, 105, 74, 0.10), transparent 70%);
  opacity: 0;
  transition: opacity 0.35s ease;
}

.x-hero.is-live::before { opacity: 1; }

/* Stretched link: the whole card is clickable, but the copy button sits above. */
.x-contact__card { position: relative; align-items: flex-start; }
.x-contact__cardlink { display: block; }
.x-contact__cardlink::after { content: ""; position: absolute; inset: 0; }
.x-contact__cardlink:focus-visible { outline: none; }
.x-contact__card:focus-within { border-color: var(--x-dark); }

.x-contact__copy {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-sm);
  background: var(--x-bg);
  color: var(--x-muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.2s ease, color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}

/* Revealed on hover or keyboard focus — never permanently visible clutter. */
.x-contact__card:hover .x-contact__copy,
.x-contact__copy:focus-visible { opacity: 1; }
.x-contact__copy:hover { color: var(--x-ink); border-color: var(--x-line-strong); }

.x-contact__copy.is-copied {
  opacity: 1;
  background: var(--x-dark);
  border-color: var(--x-dark);
  color: var(--x-bg);
}

/* The icon swaps to a tick without a second SVG in the markup. */
.x-contact__copy.is-copied .x-contact__copyicon { display: none; }
.x-contact__copy.is-copied::after {
  content: "✓";
  font-size: 0.8125rem;
  line-height: 1;
}

.x-cform__count {
  font-size: 0.6875rem;
  color: var(--x-muted);
  font-variant-numeric: tabular-nums;
}
.x-cform__count:empty { display: none; }
.x-cform__count.is-near { color: var(--x-danger); font-weight: 500; }

/* Focus lifts the label, so the active field is obvious at a glance. */
.x-cform__field:focus-within .x-cform__label { color: var(--x-ink); }

@media (prefers-reduced-motion: reduce) {
  .x-hero::before { display: none; }
  .x-contact__copy { transition: none; }
}

.x-cform__again { margin-top: 1.75rem; }

/* ── About page ───────────────────────────────────────────────────────────── */

.x-about__eyebrow {
  margin: 0 0 0.75rem;
  font-size: clamp(0.625rem, 1vw, 0.6875rem);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--x-accent);
  text-align: center;
}
.x-about__eyebrow.is-left { text-align: left; }
.x-about__eyebrow.is-light { color: rgba(244, 241, 234, 0.75); }




.x-hero + .x-container.x-about__story { padding-top: clamp(2rem, 5vw, 3.5rem); }

.x-about__heading {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.5vw, 2.25rem);
  line-height: 1.15;
  text-align: center;
  margin: 0 0 clamp(1.5rem, 3.5vw, 2.5rem);
}

/* ── Story ────────────────────────────────────────────────────────────────── */

.x-about__story {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
}

/* ⚠️ TWO COLUMNS ONLY WHEN THERE IS AN IMAGE TO FILL ONE.
   The image is optional, and without this the text sat in the left half with a
   large empty column beside it — which reads as a picture that failed to load
   rather than a section that never had one. */
@media (min-width: 1024px) {
  .x-about__story:has(.x-about__storyimg) { grid-template-columns: 0.9fr 1.1fr; }
}

/* No image: a centred reading column rather than a full-width slab. */
.x-about__story:not(:has(.x-about__storyimg)) .x-about__storytext {
  max-width: 46rem;
  margin-inline: auto;
}
.x-about__story:not(:has(.x-about__storyimg)) .x-about__eyebrow.is-left,
.x-about__story:not(:has(.x-about__storyimg)) .x-about__storytext h2 { text-align: center; }
.x-about__story:not(:has(.x-about__storyimg)) .x-about__storytext p { margin-inline: auto; }

.x-about__storyimg img {
  width: 100%;
  border-radius: clamp(1.25rem, 2vw, 1.75rem);
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--x-surface);
}

.x-about__storytext h2 {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.5vw, 2.125rem);
  line-height: 1.15;
  margin: 0 0 1rem;
}

.x-about__storytext p {
  margin: 0 0 1rem;
  color: var(--x-ink-soft);
  font-size: clamp(0.875rem, 1.1vw, 0.9375rem);
  line-height: 1.8;
  max-width: 62ch;
}

.x-about__quote {
  margin: 1.75rem 0 0;
  padding-left: 1.25rem;
  border-left: 2px solid var(--x-accent);
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 2vw, 1.375rem);
  line-height: 1.4;
  color: var(--x-ink);
}

/* ── Values ───────────────────────────────────────────────────────────────── */

.x-about__values { padding-block: clamp(2.5rem, 6vw, 4.5rem); }

.x-about__cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: clamp(0.75rem, 1.5vw, 1rem);
}

.x-about__card {
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  transition: border-color 0.2s ease, transform 0.2s ease;
}
.x-about__card:hover { border-color: var(--x-line-strong); transform: translateY(-2px); }

.x-about__card h3 { font-family: var(--font-body); font-size: 0.9375rem; font-weight: 600; margin: 1rem 0 0.5rem; }
.x-about__card p { margin: 0; font-size: 0.8125rem; line-height: 1.7; color: var(--x-ink-soft); }

.x-about__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--x-r-md);
  background: var(--x-surface-warm);
  color: var(--x-ink);
}

/* ── Figures ──────────────────────────────────────────────────────────────── */

.x-about__stats {
  background: var(--x-dark);
  color: var(--x-bg);
  padding-block: clamp(2rem, 5vw, 3.5rem);
}

.x-about__statgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: clamp(1.5rem, 3vw, 2rem);
  text-align: center;
}

.x-about__statvalue {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2rem, 5vw, 3rem);
  line-height: 1;
  /* Figures line up under one another when they sit in a row. */
  font-variant-numeric: tabular-nums;
}

.x-about__statlabel {
  display: block;
  margin-top: 0.625rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: rgba(244, 241, 234, 0.7);
}

/* ── Process ──────────────────────────────────────────────────────────────── */

.x-about__process {
  background: var(--x-bg-alt);
  border-block: 1px solid var(--x-line);
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
}

.x-about__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  counter-reset: none;
}

.x-about__steps li { position: relative; }
.x-about__steps h3 { font-family: var(--font-body); font-size: 0.9375rem; font-weight: 600; margin: 0.875rem 0 0.5rem; }
.x-about__steps p { margin: 0; font-size: 0.8125rem; line-height: 1.7; color: var(--x-ink-soft); }

.x-about__stepno {
  display: block;
  margin-top: 0.875rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--x-muted);
  font-variant-numeric: tabular-nums;
}

/* ── Closing CTA ──────────────────────────────────────────────────────────── */

.x-about__ctawrap { padding-block: clamp(2.5rem, 6vw, 4.5rem); }

.x-about__cta {
  background: var(--x-dark);
  color: var(--x-bg);
  border-radius: clamp(1.25rem, 2.5vw, 2rem);
  padding: clamp(2rem, 5vw, 3.5rem) clamp(1.25rem, 4vw, 3rem);
  text-align: center;
}

.x-about__cta h2 {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.5vw, 2.25rem);
  line-height: 1.15;
  color: var(--x-bg);
  margin: 0 0 0.875rem;
}

.x-about__ctatext {
  max-width: 46ch;
  margin: 0 auto clamp(1.5rem, 3vw, 2rem);
  color: rgba(244, 241, 234, 0.72);
  font-size: clamp(0.875rem, 1.1vw, 0.9375rem);
  line-height: 1.7;
}

.x-btn--light { background: var(--x-bg); color: var(--x-dark); }
.x-btn--light:hover { background: var(--x-white); color: var(--x-dark); }

/* ── Motion ───────────────────────────────────────────────────────────────── */

.x-about__hero .x-about__eyebrow { animation: x-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.05s both; }

@media (prefers-reduced-motion: reduce) {
  .x-about__card { transition: none; }
  .x-about__card:hover { transform: none; }
}

/* ── Track order ──────────────────────────────────────────────────────────── */



/* Ambient marks. Low contrast on purpose — texture, not decoration competing
   with the heading. */
.x-hero__deco {
  position: absolute;
  border-radius: var(--x-r-pill);
  pointer-events: none;
  background: radial-gradient(circle, rgba(201, 105, 74, 0.16), transparent 70%);
}
.x-hero__deco--1 { width: 12rem; height: 12rem; top: -3rem; left: -3rem; }
.x-hero__deco--2 { width: 16rem; height: 16rem; bottom: -6rem; right: -4rem; }
.x-hero__deco--3 { width: 8rem; height: 8rem; top: 30%; right: 18%; opacity: 0.6; }

@media (max-width: 767px) { .x-hero__deco--3 { display: none; } }




.x-track { padding-block: 0 clamp(3rem, 6vw, 5rem); }

/* ⚠️ THE HEADER BAND IS `position: relative`, SO IT PAINTS ABOVE STATIC
   CONTENT. Without a stacking context of its own, the grid was pulled up by
   the negative margin and then covered by the band — the tops of both cards
   were sliced off. */
.x-track__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(0.875rem, 2vw, 1.5rem);
  align-items: stretch;
}

/* ⚠️ THE FORM IS THE NARROWER COLUMN. It holds two fields; the result holds an
   order. Equal halves left the result cramped and the form full of air. */
@media (min-width: 1024px) {
  .x-track__grid { grid-template-columns: 0.85fr 1.15fr; }
}

.x-track__panel,
.x-track__result {
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: clamp(1.25rem, 2vw, 1.75rem);
  padding: clamp(1.25rem, 3vw, 2rem);
}

.x-track__panelhead { display: flex; align-items: flex-start; gap: 0.875rem; margin-bottom: 1.5rem; }

.x-track__panelicon {
  display: flex; align-items: center; justify-content: center;
  width: 2.375rem; height: 2.375rem; flex: 0 0 auto;
  border-radius: var(--x-r-md);
  background: var(--x-surface-warm);
  color: var(--x-ink);
}

.x-track__panelhead h2 { font-family: var(--font-display); font-size: 1.25rem; line-height: 1.2; margin: 0; }
.x-track__panelhead p { margin: 0.25rem 0 0; font-size: 0.75rem; color: var(--x-muted); }

.x-track__form { display: grid; gap: 1rem; }

.x-track__fieldlabel {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--x-muted);
}

.x-track__submit {
  width: 100%;
  margin-top: 0.25rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.75rem;
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.2s ease, opacity 0.2s ease;
}
.x-track__submit:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(30, 29, 27, 0.16); }
.x-track__submit:active { transform: translateY(0); }
.x-track__submit:disabled { transform: none; box-shadow: none; }

.x-track__tip { margin: 1rem 0 0; font-size: 0.75rem; line-height: 1.6; color: var(--x-muted); }
.x-track__rule { border: 0; border-top: 1px solid var(--x-line); margin: 1.25rem 0; }
.x-track__alt { margin: 0; font-size: 0.8125rem; color: var(--x-muted); }
.x-track__alt a { color: var(--x-ink); font-weight: 500; text-decoration: underline; text-underline-offset: 2px; }

/* ── Result panel ─────────────────────────────────────────────────────────── */

.x-track__result { display: flex; flex-direction: column; }

.x-track__placeholder {
  margin: auto;
  text-align: center;
  padding: clamp(2rem, 5vw, 3rem) 1rem;
  max-width: 34ch;
}

.x-track__placeicon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 3.5rem; height: 3.5rem;
  border-radius: var(--x-r-pill);
  background: var(--x-surface-warm);
  color: var(--x-muted);
  margin-bottom: 1.25rem;
}

.x-track__placetitle { font-family: var(--font-display); font-size: 1.25rem; margin: 0 0 0.5rem; }
.x-track__placebody { margin: 0; font-size: 0.8125rem; line-height: 1.7; color: var(--x-muted); }

/* The card replaces the placeholder inside the same panel, so nothing moves. */
.x-track__card { animation: x-rise 0.4s cubic-bezier(0.22, 1, 0.36, 1) both; }

.x-track__top {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 0.75rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--x-line);
}

.x-track__number { display: block; font-family: var(--font-display); font-size: 1.5rem; line-height: 1.2; }

.x-track__status {
  padding: 0.3rem 0.75rem; border-radius: var(--x-r-pill);
  font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  background: var(--x-surface-warm); color: #3a362e;
}

/* Status carries meaning, so it carries semantic colour — not the brand accent. */
.x-track__status[data-state="completed"] { background: #e3efe6; color: #2f6b41; }
.x-track__status[data-state="processing"] { background: #efe7dd; color: #8a5a2b; }
.x-track__status[data-state="cancelled"],
.x-track__status[data-state="failed"],
.x-track__status[data-state="refunded"] { background: #fbf0ed; color: #8a3b2e; }

.x-track__steps {
  list-style: none; display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem; margin: 1.5rem 0; padding: 0; position: relative;
}

.x-track__step { text-align: center; position: relative; }

/* The rail is drawn per-step so it can never outrun the last dot. */
.x-track__step:not(:first-child)::before {
  content: ""; position: absolute; top: 0.4375rem; right: 50%; left: -50%;
  height: 2px; background: var(--x-line);
}
.x-track__step.is-done:not(:first-child)::before { background: var(--x-dark); }

.x-track__dot {
  position: relative; z-index: 1; display: block;
  width: 1rem; height: 1rem; margin: 0 auto 0.5rem;
  border-radius: var(--x-r-pill); background: var(--x-bg); border: 2px solid var(--x-line);
}
.x-track__step.is-done .x-track__dot { background: var(--x-dark); border-color: var(--x-dark); }
.x-track__step.is-current .x-track__dot { box-shadow: 0 0 0 4px rgba(30, 29, 27, 0.12); }

.x-track__steplabel { display: block; font-size: 0.6875rem; line-height: 1.4; color: var(--x-muted); }
.x-track__step.is-done .x-track__steplabel { color: var(--x-ink); font-weight: 500; }

.x-track__items { list-style: none; margin: 0 0 1.25rem; padding: 0; display: grid; gap: 0.75rem; }

.x-track__item {
  display: grid; grid-template-columns: 2.5rem 1fr auto auto;
  align-items: center; gap: 0.75rem; font-size: 0.875rem;
}

.x-track__item img, .x-track__noimg {
  width: 2.5rem; height: 2.5rem; border-radius: var(--x-r-sm);
  object-fit: cover; background: var(--x-surface); display: block;
}

.x-track__itemname { min-width: 0; overflow-wrap: anywhere; }
.x-track__itemqty { color: var(--x-muted); font-variant-numeric: tabular-nums; }
.x-track__itemtotal { font-weight: 500; font-variant-numeric: tabular-nums; }

.x-track__meta {
  margin: 0; padding-top: 1.25rem; border-top: 1px solid var(--x-line);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); gap: 1rem;
}
.x-track__meta dt { font-size: 0.5625rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--x-muted); }
.x-track__meta dd { margin: 0.25rem 0 0; font-size: 0.875rem; }

@media (prefers-reduced-motion: reduce) {
  .x-track__card { animation: none; }
  .x-track__submit { transition: none; }
  .x-track__submit:hover { transform: none; box-shadow: none; }
}

/* ── Sitewide offer ───────────────────────────────────────────────────────── */

.x-offer-flag {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 2;
  padding: 0.25rem 0.625rem;
  border-radius: var(--x-r-pill);
  background: var(--x-accent);
  color: var(--x-white);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.5;
}

.woocommerce div.product .x-offer-flag { top: 1rem; left: 1rem; }
.woocommerce div.product div.images { position: relative; }

/*
 * ⚠️ THE STRUCK-THROUGH PRICE IS THE QUIETER OF THE TWO.
 * WooCommerce renders <del>MRP</del><ins>offer</ins>; without this they carry
 * equal weight and the eye cannot tell which number it pays.
 */
.woocommerce .price del,
.x-card__price del {
  color: var(--x-muted);
  font-weight: 400;
  text-decoration-thickness: 1px;
  margin-right: 0.4rem;
  opacity: 0.85;
}

.woocommerce .price ins,
.x-card__price ins {
  text-decoration: none;
  font-weight: 600;
  color: var(--x-ink);
}

.woocommerce div.product p.price ins { font-size: inherit; }
.woocommerce div.product p.price del { font-size: 1rem; }

/* ── Shared motion ────────────────────────────────────────────────────────────
 *
 * ⚠️ THE HIDDEN STATE IS ARMED BY JAVASCRIPT, NOT BY DEFAULT.
 *
 * `.x-reveal` elements are fully visible until motion.js adds `x-reveal-on` to
 * <html> — which it only does once it has confirmed it can reveal them again.
 * Written the other way round, a blocked script leaves the page blank. That is
 * the exact failure that hid the contact sidebar on phones earlier.
 */
html.x-reveal-on .x-reveal {
  opacity: 0;
  transform: translateY(16px);
}

html.x-reveal-on .x-reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Sheen on any hero, not just the contact page. */
.x-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(22rem 22rem at var(--x-mx, 50%) var(--x-my, 50%), rgba(201, 105, 74, 0.10), transparent 70%);
  opacity: 0;
  transition: opacity 0.35s ease;
}
.x-hero.is-live::before { opacity: 1; }

/* The header gains an edge once the page moves under it, so the sticky bar
   reads as being above the content rather than part of it. */
.x-header { transition: box-shadow 0.25s ease, background-color 0.25s ease; }
.x-header.is-stuck { box-shadow: 0 1px 16px rgba(30, 29, 27, 0.06); }

/* Product imagery lifts slightly under the pointer — the card itself stays put
   so a row of them does not ripple. */
.woocommerce ul.products li.product img { transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
.woocommerce ul.products li.product:hover img { transform: scale(1.03); }

.x-about__statvalue { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  html.x-reveal-on .x-reveal { opacity: 1; transform: none; }
  .x-hero::before { display: none; }
  .x-header { transition: none; }
  .woocommerce ul.products li.product img,
  .woocommerce ul.products li.product:hover img { transition: none; transform: none; }
}

/* ── Ambience ─────────────────────────────────────────────────────────────────
 *
 * The empty cart had a drifting wash, a floating mark and a springy entrance;
 * every other page stopped moving the moment it arrived. These bring the rest
 * up to the same standard rather than adding a different kind of motion.
 */

.x-hero {
  /* Flat colour cannot drift. A wash barely off the base gives the animation
     something to move without the band reading as a gradient. */
  background: linear-gradient(120deg, var(--x-bg-alt) 0%, #efe9e1 45%, #f2eae4 100%);
  background-size: 200% 200%;
  animation: x-drift 26s ease-in-out infinite;
}

/* The brand mark breathes rather than sitting still. */
.x-hero__mark {
  animation:
    x-rise 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.20s both,
    x-twinkle 4.5s ease-in-out 1s infinite;
}

/*
 * ⚠️ THE OVERSHOOT IS ON THE REVEAL, NOT ON EVERY TRANSITION.
 * A slight past-the-mark settle reads as physical; applied to hovers and colour
 * changes it just reads as sloppy timing.
 */
html.x-reveal-on .x-reveal.is-in {
  transition: opacity 0.5s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.6s cubic-bezier(0.34, 1.28, 0.64, 1);
}

/* Icon tiles react; the card they sit in stays still, so a row does not ripple. */
.x-about__icon,
.x-contact__icon,
.x-track__panelicon {
  transition: background-color 0.25s ease, color 0.25s ease,
              transform 0.3s cubic-bezier(0.34, 1.4, 0.64, 1);
}

.x-about__card:hover .x-about__icon,
.x-about__steps li:hover .x-about__icon {
  background: var(--x-dark);
  color: var(--x-bg);
  transform: translateY(-3px) scale(1.06);
}

.x-about__steps li { transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1); }
.x-about__steps li:hover { transform: translateY(-2px); }

/* The waiting package drifts like the empty cart's bag — it signals "nothing
   yet" without a spinner implying something is loading. */
.x-track__placeicon { animation: x-float 5s ease-in-out 0.5s infinite; }

/* Buttons everywhere get the empty cart's lift-and-shadow. */
.x-btn,
.woocommerce a.button,
.woocommerce button.button {
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.2s ease, opacity 0.2s ease, background-color 0.2s ease;
}

.x-btn:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover { box-shadow: 0 8px 20px rgba(30, 29, 27, 0.14); }

.x-btn--accent:hover { box-shadow: 0 8px 20px rgba(201, 105, 74, 0.28); }
.x-btn:active, .woocommerce button.button:active { transform: translateY(0); box-shadow: none; }
.x-btn:disabled, .woocommerce button.button:disabled { transform: none; box-shadow: none; }

/* Statistics band: the figures land, they do not fade. */
.x-about__stats.is-in .x-about__statvalue { animation: x-pop 0.5s cubic-bezier(0.34, 1.4, 0.64, 1) both; }
.x-about__statgrid > div:nth-child(2) .x-about__statvalue { animation-delay: 0.08s; }
.x-about__statgrid > div:nth-child(3) .x-about__statvalue { animation-delay: 0.16s; }

@media (prefers-reduced-motion: reduce) {
  .x-hero,
  .x-hero__mark,
  .x-track__placeicon,
  .x-about__stats.is-in .x-about__statvalue { animation: none !important; }

  .x-hero { background: var(--x-bg-alt); }

  .x-about__icon, .x-contact__icon, .x-track__panelicon,
  .x-about__steps li, .x-btn, .woocommerce button.button { transition: none; }

  .x-about__card:hover .x-about__icon,
  .x-about__steps li:hover .x-about__icon,
  .x-about__steps li:hover,
  .x-btn:hover, .woocommerce button.button:hover { transform: none; box-shadow: none; }
}

/* ── Homepage ─────────────────────────────────────────────────────────────── */

.x-hero__eyebrow.is-left { text-align: left; }
.x-home__heading.is-left { text-align: left; }

.x-home__hero {
  background: linear-gradient(120deg, var(--x-bg-alt) 0%, #efe9e1 45%, #f4ece7 100%);
  border-bottom: 1px solid var(--x-line);
  padding-block: clamp(2rem, 5vw, 4rem);
}

.x-home__herogrid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
}

@media (min-width: 1024px) { .x-home__herogrid { grid-template-columns: 1fr 0.9fr; } }

.x-home__herotitle {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5.5vw, 3.75rem);
  line-height: 1.05;
  margin: 0 0 clamp(0.75rem, 2vw, 1.25rem);
  animation: x-rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.1s both;
}

.x-home__herolead {
  max-width: 46ch;
  margin: 0 0 clamp(1.5rem, 3vw, 2rem);
  color: var(--x-ink-soft);
  font-size: clamp(0.9375rem, 1.2vw, 1.0625rem);
  line-height: 1.7;
  animation: x-rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.18s both;
}

.x-home__herocta { animation: x-rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) 0.26s both; }

.x-home__heroimg img {
  width: 100%;
  border-radius: clamp(1.25rem, 2.5vw, 2rem);
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--x-surface);
  animation: x-rise 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.2s both;
}

@media (min-width: 1024px) { .x-home__heroimg img { aspect-ratio: 5 / 6; } }

/* ── Promises ─────────────────────────────────────────────────────────────── */

.x-home__promises { border-bottom: 1px solid var(--x-line); background: var(--x-white); }

.x-home__promisegrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: clamp(1rem, 2.5vw, 2rem);
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
}

.x-home__promise { display: flex; align-items: flex-start; gap: 0.75rem; }
.x-home__promise strong { display: block; font-size: 0.875rem; font-weight: 600; }
.x-home__promise span { display: block; margin-top: 0.125rem; font-size: 0.75rem; line-height: 1.5; color: var(--x-muted); }

.x-home__promiseicon {
  display: flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; flex: 0 0 auto;
  border-radius: var(--x-r-sm);
  background: var(--x-surface-warm);
  color: var(--x-ink);
}

/* ── Sections ─────────────────────────────────────────────────────────────── */

.x-home__section { padding-block: clamp(2.5rem, 6vw, 4.5rem); }

.x-home__heading {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.5vw, 2.25rem);
  line-height: 1.15;
  text-align: center;
  margin: 0 0 clamp(1.5rem, 3.5vw, 2.5rem);
}

.x-home__railhead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
}
.x-home__railhead .x-home__heading { margin: 0; }

.x-home__seeall {
  flex: 0 0 auto;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--x-ink);
  border-bottom: 1px solid var(--x-line-strong);
  /* Measured at 37×24. The underline stays where it is; the hit area grows
     around it, which is invisible and doubles the chance of landing it. */
  padding: 0.6rem 0.25rem 0.5rem;
  margin: -0.6rem -0.25rem -0.5rem;
  touch-action: manipulation;
}
.x-home__seeall:hover { border-bottom-color: var(--x-dark); }

/* ── Category tiles ───────────────────────────────────────────────────────── */

/*
 * ⚠️ ONE SCROLLING ROW ON A PHONE, A GRID ON DESKTOP.
 *
 * Six tiles at two-up is three stacked rows — 660px of vertical scroll spent on
 * navigation before a customer reaches a single product. A horizontal rail
 * shows the same six, costs about a third of the height, and matches how the
 * bestsellers above it already behave, so the gesture is already learned.
 */
.x-home__cats {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 42%;
  gap: clamp(0.625rem, 1.5vw, 1rem);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Bleed to the screen edge so a half-visible tile signals "scrollable". */
  margin-inline: calc(var(--x-pad) * -1);
  padding-inline: var(--x-pad);
  padding-bottom: 0.25rem;
}
.x-home__cats::-webkit-scrollbar { display: none; }
.x-home__cats > * { scroll-snap-align: start; }

@media (min-width: 48rem) {
  .x-home__cats {
    grid-auto-flow: row;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
    overflow: visible;
    margin-inline: 0;
    padding-inline: 0;
  }
}

.x-home__cat {
  display: block;
  text-align: center;
  padding: clamp(1rem, 2vw, 1.5rem) 0.75rem;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  transition: border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
.x-home__cat:hover { border-color: var(--x-line-strong); transform: translateY(-2px); box-shadow: 0 8px 20px rgba(30,29,27,.05); }

.x-home__catimg {
  display: flex; align-items: center; justify-content: center;
  width: 4rem; height: 4rem; margin: 0 auto 0.75rem;
  border-radius: var(--x-r-pill);
  background: var(--x-surface-warm);
  overflow: hidden;
}
.x-home__catimg img { width: 100%; height: 100%; object-fit: cover; }

.x-home__catname { display: block; font-size: 0.875rem; font-weight: 500; }
.x-home__catcount { display: block; margin-top: 0.125rem; font-size: 0.6875rem; color: var(--x-muted); }

/* ── Product rail ─────────────────────────────────────────────────────────── */

/*
 * ⚠️ A SCROLL-SNAP RAIL, NOT A SCRIPTED CAROUSEL.
 * It works with a trackpad, a touchscreen, arrow keys, a screen reader and no
 * JavaScript at all — and it cannot desynchronise from its own dot indicators,
 * because it has none.
 */
.woocommerce ul.products.x-home__rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(14rem, 1fr);
  grid-template-columns: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--x-pad);
  gap: 1rem;
  /*
   * ⚠️ `overflow-x: auto` CLIPS VERTICALLY TOO.
   *
   * A scroll container on one axis still clips the other — there is no
   * "scroll sideways, overflow freely upwards". So the card's 2px hover lift
   * was being sliced off flat against the top edge, on the rails only; the
   * shop grid is not a scroll container and never showed it.
   *
   * The padding gives the lift somewhere to go and the negative margin takes
   * the same amount back off the layout, so the gap below the heading is
   * unchanged.
   */
  padding-top: 0.5rem;
  margin-top: -0.5rem;
  padding-bottom: 0.5rem;
  /* The scrollbar is left visible: hiding it removes the only cue that there is
     more to the right. */
}

.woocommerce ul.products.x-home__rail li.product { scroll-snap-align: start; }

/* ⚠️ THE CARD KEEPS ITS WIDTH AT EVERY SIZE.
   Letting eight cards share the container on desktop squeezed each to ~9rem —
   product names wrapped to four lines and the Add to Bag / Buy Now pair was
   clipped to "dd to B". A rail scrolls; it does not compress. */
@media (min-width: 768px) {
  .woocommerce ul.products.x-home__rail { grid-auto-columns: minmax(15rem, 1fr); }
}

/* Bleed the rail to the viewport edge so a partially-visible card signals that
   there is more, instead of stopping flush with the container. */
@media (min-width: 1024px) {
  .woocommerce ul.products.x-home__rail { grid-auto-columns: 17rem; }
}

/* ── Offer strip ──────────────────────────────────────────────────────────── */

.x-home__stripwrap { padding-block: clamp(1rem, 2vw, 1.5rem); }

.x-home__strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1rem, 3vw, 2rem);
  background: var(--x-dark);
  color: var(--x-bg);
  border-radius: clamp(1.25rem, 2.5vw, 2rem);
  padding: clamp(1.5rem, 4vw, 2.5rem) clamp(1.25rem, 4vw, 3rem);
}

.x-home__strip h2 {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 3vw, 1.875rem);
  line-height: 1.2;
  color: var(--x-bg);
  margin: 0;
}
.x-home__strip p { margin: 0.5rem 0 0; max-width: 52ch; font-size: 0.875rem; line-height: 1.6; color: rgba(244,241,234,.72); }

/* ── Story band ───────────────────────────────────────────────────────────── */

.x-home__story { background: var(--x-bg-alt); border-block: 1px solid var(--x-line); }

.x-home__storygrid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
}
@media (min-width: 1024px) { .x-home__storygrid { grid-template-columns: 0.9fr 1.1fr; } }

.x-home__storyimg img {
  width: 100%;
  border-radius: clamp(1.25rem, 2vw, 1.75rem);
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--x-surface);
}

.x-home__storytext h2 {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.5vw, 2.125rem);
  line-height: 1.15;
  margin: 0 0 1rem;
}
.x-home__storytext p { margin: 0 0 1rem; max-width: 60ch; color: var(--x-ink-soft); font-size: 0.9375rem; line-height: 1.8; }
.x-home__storytext .x-btn { margin-top: 0.5rem; }

/* ── Reviews ──────────────────────────────────────────────────────────────── */

.x-home__reviews {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: clamp(0.75rem, 1.5vw, 1rem);
}

.x-home__review {
  position: relative;
  margin: 0;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
}

.x-home__quotemark {
  position: absolute;
  top: 0.25rem; right: 1rem;
  font-family: var(--font-display);
  font-size: 3.5rem;
  line-height: 1;
  color: var(--x-line);
}

.x-home__review blockquote { margin: 0 0 1rem; font-size: 0.9375rem; line-height: 1.7; color: var(--x-ink); }
.x-home__review figcaption strong { display: block; font-size: 0.8125rem; }
.x-home__review figcaption span { display: block; margin-top: 0.125rem; font-size: 0.75rem; color: var(--x-muted); }

/* ── Newsletter ───────────────────────────────────────────────────────────── */

.x-home__newswrap { padding-block: clamp(1rem, 2vw, 1.5rem) clamp(3rem, 6vw, 4.5rem); }

.x-home__news {
  text-align: center;
  background: var(--x-surface-warm);
  border: 1px solid var(--x-line);
  border-radius: clamp(1.25rem, 2.5vw, 2rem);
  padding: clamp(2rem, 5vw, 3.5rem) 1.5rem;
}

.x-home__news h2 { font-family: var(--font-display); font-size: clamp(1.375rem, 3vw, 2rem); margin: 0 0 0.625rem; }
.x-home__news p { max-width: 46ch; margin: 0 auto; color: var(--x-ink-soft); font-size: 0.9375rem; line-height: 1.7; }
.x-home__newscta { margin-top: 1.5rem; }

@media (prefers-reduced-motion: reduce) {
  .x-home__herotitle, .x-home__herolead, .x-home__herocta, .x-home__heroimg img { animation: none !important; }
  .x-home__cat { transition: none; }
  .x-home__cat:hover { transform: none; box-shadow: none; }
}

/* ── Shop listing ─────────────────────────────────────────────────────────── */

.x-shop { padding-block: clamp(1.5rem, 4vw, 2.5rem) clamp(3rem, 6vw, 4.5rem); }

/* The toolbar reads as one row rather than two stray controls. */
.woocommerce .woocommerce-result-count,
.woocommerce .woocommerce-ordering { margin: 0; }

.x-shop__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding-bottom: clamp(1rem, 2.5vw, 1.5rem);
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
  border-bottom: 1px solid var(--x-line);
}

.x-shop__chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.x-shop__chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.4375rem 0.875rem;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-pill);
  background: var(--x-white);
  font-size: 0.8125rem;
  color: var(--x-ink-soft);
  transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.x-shop__chip:hover { border-color: var(--x-line-strong); color: var(--x-ink); }
.x-shop__chip.is-active { background: var(--x-dark); border-color: var(--x-dark); color: var(--x-bg); }
.x-shop__chip span { font-size: 0.6875rem; opacity: 0.7; font-variant-numeric: tabular-nums; }
.x-shop__chip.is-active span { opacity: 0.6; }

.x-shop__count { font-size: 0.8125rem; color: var(--x-muted); }

/* ── Shop filters ─────────────────────────────────────────────────────────── */

.x-shop__tools { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

.x-shop__filters { position: relative; }

.x-shop__filters summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4375rem;
  padding: 0.6rem 1rem;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-md);
  background: var(--x-field);
  font-size: 0.8125rem;
  color: var(--x-ink);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.x-shop__filters summary::-webkit-details-marker { display: none; }
.x-shop__filters summary:hover { border-color: var(--x-line-strong); }
.x-shop__filters[open] summary { border-color: var(--x-dark); background: var(--x-white); }

.x-shop__badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.125rem; height: 1.125rem; padding-inline: 0.25rem;
  border-radius: var(--x-r-pill); background: var(--x-dark); color: var(--x-bg);
  font-size: 0.625rem; font-weight: 600; line-height: 1;
}

.x-shop__panel {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.5rem);
  left: 0;
  width: min(22rem, calc(100vw - 2.5rem));
  display: grid;
  gap: 1.25rem;
  padding: 1.25rem;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  box-shadow: 0 12px 32px rgba(30, 29, 27, 0.10);
  animation: x-rise 0.22s ease-out both;
}

/* Anchored to the right edge on wide screens so it cannot run off-canvas. */
@media (min-width: 640px) { .x-shop__panel { left: auto; right: 0; } }

.x-shop__panel fieldset { border: 0; margin: 0; padding: 0; display: grid; gap: 0.625rem; }
.x-shop__panel legend {
  padding: 0;
  font-size: 0.625rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--x-muted);
}

.x-shop__range { display: flex; align-items: center; gap: 0.5rem; }
.x-shop__range label { flex: 1; min-width: 0; }
.x-shop__range input {
  width: 100%;
  border: 1px solid var(--x-line);
  background: var(--x-field);
  border-radius: var(--x-r-sm);
  padding: 0.5rem 0.75rem;
  font-family: var(--font-body);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  color: var(--x-ink);
}
.x-shop__range input:focus { outline: none; border-color: var(--x-dark); background: var(--x-white); }
.x-shop__range span { color: var(--x-muted); }

.x-shop__hint { margin: 0; font-size: 0.6875rem; color: var(--x-muted); }

.x-shop__check { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; color: var(--x-ink); cursor: pointer; }

.x-shop__panelfoot { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.x-shop__panelfoot .x-btn { padding: 0.6rem 1.5rem; font-size: 0.75rem; }
.x-shop__clear { font-size: 0.8125rem; color: var(--x-muted); text-decoration: underline; text-underline-offset: 2px; }
.x-shop__clear:hover { color: var(--x-ink); }

/* ── Active filters ───────────────────────────────────────────────────────── */

.x-shop__active {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  margin: -0.5rem 0 clamp(1.25rem, 3vw, 1.75rem);
}

.x-shop__activelabel { font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--x-muted); }

/* Each pill is a link that removes its own filter — one tap, no panel. */
.x-shop__pill {
  display: inline-flex; align-items: center; gap: 0.4375rem;
  padding: 0.3125rem 0.6875rem;
  border-radius: var(--x-r-pill);
  background: var(--x-surface-warm);
  border: 1px solid var(--x-line);
  font-size: 0.75rem; color: var(--x-ink);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.x-shop__pill:hover { background: var(--x-dark); border-color: var(--x-dark); color: var(--x-bg); }
.x-shop__pill span[aria-hidden] { font-size: 0.875rem; line-height: 1; opacity: 0.6; }

@media (prefers-reduced-motion: reduce) {
  .x-shop__panel { animation: none; }
  .x-shop__pill { transition: none; }
}

.x-shop__concerns { display: grid; grid-template-columns: 1fr 1fr; gap: 0.375rem 0.75rem; }

.x-shop__concern {
  display: flex; align-items: center; gap: 0.4375rem;
  font-size: 0.8125rem; color: var(--x-ink); cursor: pointer;
  min-width: 0;
}
.x-shop__concern span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.x-shop__concern em { font-style: normal; font-size: 0.6875rem; color: var(--x-muted); font-variant-numeric: tabular-nums; }
.x-shop__concern input { flex: 0 0 auto; }

/* Nine concerns need the room; the panel widens rather than the labels wrapping. */
@media (min-width: 640px) { .x-shop__panel { width: min(26rem, calc(100vw - 2.5rem)); } }

/* ────────────────────────────────────────────────────────────────────────────
 * The bag drawer
 * ──────────────────────────────────────────────────────────────────────────── */

/*
 * ⚠️ ABOVE THE HEADER, WHICH SITS AT `z-index: 50`.
 * A modal the sticky header can cover is not a modal — the panel would slide in
 * underneath the navigation and lose its own close button off the top.
 */
.x-drawer {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  justify-content: flex-end;
}

.x-drawer[hidden] { display: none; }

.x-drawer__scrim {
  position: absolute;
  inset: 0;
  border: 0;
  padding: 0;
  cursor: pointer;
  background: rgba(24, 20, 18, 0.45);
  opacity: 0;
  transition: opacity 0.3s ease;
}

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

.x-drawer__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(26rem, 100%);
  max-width: 100%;
  height: 100%;
  background: var(--x-bg);
  border-left: 1px solid var(--x-line);
  transform: translateX(100%);
  transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}

.x-drawer.is-open .x-drawer__panel { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .x-drawer__panel,
  .x-drawer__scrim { transition: none; }
}

.x-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.125rem 1.25rem;
  border-bottom: 1px solid var(--x-line);
  flex: 0 0 auto;
}

.x-drawer__title {
  font-family: var(--font-display);
  font-size: 1.375rem;
  margin: 0;
}

.x-drawer__close {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-pill);
  background: transparent;
  color: var(--x-ink);
  cursor: pointer;
}

.x-drawer__close:hover { background: var(--x-surface); }

/*
 * ⚠️ THE SCROLLING REGION IS THE CONTENT, NOT THE PANEL.
 * With the panel scrolling, the Checkout button scrolls away with a long bag —
 * the one control the drawer exists to reach.
 */
.x-drawer__content {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain; /* stops the page behind scrolling at the ends */
}

.x-drawer.is-busy .x-drawer__content { opacity: 0.55; pointer-events: none; }
.x-drawer__content { transition: opacity 0.15s ease; }

.x-drawer__items {
  list-style: none;
  margin: 0;
  padding: 0.5rem 1.25rem;
  flex: 1 1 auto;
}

.x-drawer__item {
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  gap: 0.875rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--x-line);
}

.x-drawer__item:last-child { border-bottom: 0; }

.x-drawer__thumb {
  display: block;
  border-radius: var(--x-r-md);
  overflow: hidden;
  background: var(--x-surface);
}

.x-drawer__thumb img { display: block; width: 100%; height: auto; }

.x-drawer__detail { display: flex; flex-direction: column; gap: 0.375rem; min-width: 0; }

.x-drawer__name {
  font-size: 0.875rem;
  line-height: 1.35;
  color: var(--x-ink);
  text-decoration: none;
}

.x-drawer__name:hover { text-decoration: underline; text-underline-offset: 3px; }

.x-drawer__price { font-size: 0.875rem; font-weight: 500; }

.x-drawer__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.125rem;
}

.x-drawer__qty {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.125rem 0.375rem;
  border: 1px solid var(--x-line-strong);
  border-radius: var(--x-r-pill);
}

.x-drawer__step {
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--x-r-pill);
  background: transparent;
  color: var(--x-ink);
  font-size: 0.9375rem;
  line-height: 1;
  cursor: pointer;
}

.x-drawer__step:hover { background: var(--x-surface); }

.x-drawer__n {
  min-width: 1.25rem;
  text-align: center;
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

.x-drawer__remove {
  border: 0;
  background: none;
  padding: 0;
  font-size: 0.75rem;
  color: var(--x-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.x-drawer__remove:hover { color: var(--x-danger); }

/* ── The offer ladder ─────────────────────────────────────────────────────── */

/*
 * ⚠️ THIS IS THE FIRST THING IN THE PANEL, SO IT IS ALLOWED TO BE LOUD.
 *
 * It is the only element in the drawer that can change the size of the order —
 * everything else reports what has already been decided. As a quiet grey note
 * under the item list it was read by nobody.
 */
.x-drawer__ladder {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.875rem 1.25rem 1rem;
  border-bottom: 1px solid var(--x-line);
  background:
    radial-gradient(18rem 8rem at 85% -30%, rgba(201, 105, 74, 0.16), transparent 70%),
    var(--x-surface-warm);
}

.x-drawer__ladder.is-earned {
  background:
    radial-gradient(18rem 8rem at 85% -30%, rgba(74, 124, 89, 0.2), transparent 70%),
    color-mix(in srgb, var(--x-success) 10%, var(--x-bg));
}

.x-drawer__laddertext {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.3125rem;
  margin: 0 0 0.75rem;
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--x-ink-soft);
}

.x-drawer__laddertext strong {
  font-weight: 600;
  color: var(--x-ink);
  /* The tier is the offer; it should be readable at a glance, not parsed out
     of a sentence set at one weight. */
  font-size: 0.875rem;
}

.x-drawer__saved { color: var(--x-success); font-weight: 500; }
.x-drawer__saved .amount { font-weight: 600; }

.x-drawer__laddericon {
  display: grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: var(--x-r-pill);
  background: var(--x-success);
  color: #fff;
  flex: 0 0 auto;
}

/* ── The track ────────────────────────────────────────────────────────────── */

/*
 * A rail with a badge at each tier and its offer named underneath, filling from
 * the left as the bag grows.
 *
 * ⚠️ THE BADGES SIT ON TOP OF THE RAIL, NOT IN FLOW WITH IT.
 *
 * Laid out as a flex row, each badge's width would push the others along and
 * the rail would no longer line up with anything. They are absolutely
 * positioned from `--x-at`, so the label underneath can be any length without
 * moving the badge it belongs to.
 */
.x-drawer__track {
  position: relative;
  /* Tall enough for the badge and the two lines a long label can wrap to. */
  height: 4.5rem;
  margin: 0.25rem 0 0;
}

.x-drawer__rail,
.x-drawer__fill {
  position: absolute;
  top: 1.125rem;
  left: 0;
  height: 0.25rem;
  border-radius: var(--x-r-pill);
}

.x-drawer__rail {
  right: 0;
  background: rgba(30, 29, 27, 0.12);
}

.x-drawer__fill {
  width: var(--x-pct, 0%);
  background: linear-gradient(90deg, var(--x-accent), #d98a63);
  transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.is-earned .x-drawer__fill { background: linear-gradient(90deg, var(--x-success), #6a9c78); }

.x-drawer__rung {
  position: absolute;
  top: 0;
  left: var(--x-at, 50%);
  transform: translateX(-50%);
  width: 6rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4375rem;
  text-align: center;
}

.x-drawer__badge {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--x-r-pill);
  background: var(--x-bg);
  /* Dashed while locked — the same visual language as a stamp not yet earned. */
  border: 2px dashed var(--x-line-strong);
  color: var(--x-muted);
  transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
}

.x-drawer__rung.is-done .x-drawer__badge {
  background: var(--x-success);
  border: 2px solid var(--x-success);
  color: #fff;
  /* The halo is what makes an unlocked rung read as lit rather than merely
     filled, and it costs no layout — a border would move the badge. */
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--x-success) 22%, transparent);
}

.x-drawer__runglabel {
  font-size: 0.6875rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--x-muted);
  text-wrap: balance;
}

.x-drawer__rung.is-done .x-drawer__runglabel { color: var(--x-ink); }

/*
 * The badge pulses once as it is reached — the only motion in the panel, spent
 * on the one event worth celebrating.
 */
@keyframes x-rung-pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.28); }
  100% { transform: scale(1); }
}

@media (prefers-reduced-motion: no-preference) {
  .is-earned .x-drawer__rung.is-done .x-drawer__badge { animation: x-rung-pop 0.55s ease-out; }
}

/* ── Footer ───────────────────────────────────────────────────────────────── */

.x-drawer__foot {
  flex: 0 0 auto;
  padding: 1rem 1.25rem 1.25rem;
  border-top: 1px solid var(--x-line);
  /* Slightly lifted off the item list so the summary reads as a separate,
     settled block rather than the end of the scrolling area. */
  background: var(--x-surface-warm);
  position: sticky;
  bottom: 0;
}

/*
 * ⚠️ THE LABEL AND THE AMOUNT ARE THE ONLY TWO CHILDREN.
 *
 * `wc_price()` returns its own nested spans, so the amount is wrapped in one
 * span of ours and the flex row stays two-up — otherwise the currency symbol
 * becomes a third flex item and the row spaces into three parts.
 */
.x-drawer__line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--x-muted);
}

.x-drawer__line > span:last-child {
  color: var(--x-ink-soft);
  /* Digits line up column-wise across subtotal, discount and total. */
  font-variant-numeric: tabular-nums;
}

.x-drawer__line.is-saving > span { color: var(--x-success); font-weight: 500; }
.x-drawer__line.is-saving .amount { color: inherit; }

.x-drawer__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.625rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--x-line-strong);
  font-size: 0.875rem;
  color: var(--x-ink);
}

.x-drawer__total strong {
  font-size: 1.25rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}


.x-drawer__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin-top: 0.875rem;
}

.x-drawer__actions .x-btn {
  width: 100%;
  font-size: 0.8125rem;
  padding-inline: 0.75rem;
}

/* ── Empty ────────────────────────────────────────────────────────────────── */

.x-drawer__empty {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 2rem 1.5rem;
  text-align: center;
}

.x-drawer__emptytitle {
  font-family: var(--font-display);
  font-size: 1.25rem;
  margin: 0;
}

.x-drawer__emptytext { margin: 0 0 0.75rem; font-size: 0.875rem; color: var(--x-ink-soft); }

/* ────────────────────────────────────────────────────────────────────────────
 * The bag page
 * ──────────────────────────────────────────────────────────────────────────── */

/* No vertical padding: the page already sits inside `.x-shop`, which supplies
   it. Adding more here doubled the gap above the first item. */
.x-cart {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}

@media (min-width: 1024px) {
  /* The summary is a fixed, comfortable width; the items take what is left,
     rather than both halving the container and leaving product names to wrap. */
  .x-cart { grid-template-columns: minmax(0, 1fr) 22rem; }
}

.x-cart__main { min-width: 0; }

.x-cart__items {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  background: var(--x-white);
  overflow: hidden;
}

.x-cart .x-drawer__ladder {
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  margin-bottom: 1rem;
}

/*
 * The "any 2" bundle on the cart page — the bag drawer's block, in this page's
 * proportions. See the note in assets/cart-drawer.css.
 *
 * ⚠️ THE ROWS HERE ALREADY CARRY THEIR OWN PADDING.
 *
 * `.x-cart__item` pads itself, unlike the drawer's rows, so this block only has
 * to supply the tint and the edge — adding padding as well would indent the
 * grouped rows out of line with the ungrouped ones below them.
 */
.x-cart__bundle {
  list-style: none;
  margin: 0;
  border-bottom: 1px solid var(--x-line);
  background: rgba(185, 143, 66, .05);
}

.x-cart__bundle:last-child { border-bottom: 0; }

/*
 * "1 of 2 in this offer" — only on a line the bundle covers in part.
 * Quiet, and in the accent so it reads as part of the block around it.
 */
/*
 * "1 in the offer" — where the quantity field sits on an ordinary row.
 *
 * A split line is two rows of the same cart line: this one states what the
 * offer took, the one below carries the field and the remove link. Two fields
 * would be two ways to set one number.
 */
.x-cart__bundleqty {
  font-size: 0.6875rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--xg-accent-ink, #7e5320);
  opacity: .9;
}


.x-cart__bundlefoot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin: 0;
  padding: 0.6875rem clamp(1rem, 2.5vw, 1.25rem) 0.75rem;
  background: rgba(185, 143, 66, .08);
  border-top: 1px solid rgba(185, 143, 66, .22);
}

.x-cart__bundlename {
  font-size: 0.6875rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--xg-accent-ink, #7e5320);
}

.x-cart__bundlesums {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}

.x-cart__bundlesave { font-size: 0.8125rem; color: var(--xg-accent-ink, #7e5320); opacity: .8; }

.x-cart__bundletotal {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--x-ink);
  font-variant-numeric: tabular-nums;
}

.x-cart__bundleitems { list-style: none; margin: 0; padding: 0; }

.x-cart__bundleitems .x-cart__item { border-bottom: 0; }

.x-cart__bundleitems .x-cart__item + .x-cart__item {
  border-top: 1px solid rgba(185, 143, 66, .2);
}

.x-cart__item {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr);
  gap: clamp(0.875rem, 2vw, 1.25rem);
  padding: clamp(1rem, 2.5vw, 1.25rem);
  border-bottom: 1px solid var(--x-line);
}

.x-cart__item:last-child { border-bottom: 0; }

@media (min-width: 640px) {
  .x-cart__item { grid-template-columns: 6.5rem minmax(0, 1fr); }
}

.x-cart__thumb {
  border-radius: var(--x-r-md);
  overflow: hidden;
  background: var(--x-surface);
  aspect-ratio: 1;
}

.x-cart__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.x-cart__detail { display: flex; flex-direction: column; gap: 0.75rem; min-width: 0; }

.x-cart__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.x-cart__name {
  font-family: var(--font-display);
  font-size: clamp(1rem, 2vw, 1.1875rem);
  line-height: 1.25;
  margin: 0;
}

.x-cart__name a { color: var(--x-ink); text-decoration: none; }
.x-cart__name a:hover { text-decoration: underline; text-underline-offset: 3px; }

.x-cart__unit {
  margin: 0.25rem 0 0;
  font-size: 0.8125rem;
  color: var(--x-muted);
}

.x-cart__unit span { font-size: 0.75rem; }

/* The line total is the number being scanned down the column, so it is the one
   with weight — the per-unit price above it is reference, not decision. */
.x-cart__money {
  font-size: 1rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.x-cart__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: auto;
}

.x-cart__qty .quantity { display: flex; }

/* WooCommerce's own number input, restyled rather than replaced — its name
   attribute is what the update handler reads. */
.x-cart__qty input[type="number"] {
  width: 4.5rem;
  height: 2.375rem;
  padding: 0 0.5rem;
  text-align: center;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  color: var(--x-ink);
  background: var(--x-field);
  border: 1px solid var(--x-line-strong);
  border-radius: var(--x-r-pill);
}

.x-cart__qty input[type="number"]:focus-visible {
  outline: 2px solid var(--x-dark);
  outline-offset: 1px;
}

.x-cart__one { font-size: 0.8125rem; color: var(--x-muted); }

.x-cart__remove {
  font-size: 0.75rem;
  color: var(--x-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.x-cart__remove:hover { color: var(--x-danger); }

.x-cart__tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1rem;
  margin-top: 1rem;
}

.x-cart__coupon { display: flex; gap: 0.5rem; flex: 1 1 16rem; }

.x-cart__coupon input {
  flex: 1 1 auto;
  min-width: 0;
  height: 2.75rem;
  padding: 0 1rem;
  font-size: 0.875rem;
  background: var(--x-white);
  border: 1px solid var(--x-line-strong);
  border-radius: var(--x-r-pill);
  color: var(--x-ink);
}

.x-cart__coupon input::placeholder { color: var(--x-muted); }
.x-cart__coupon .x-btn { flex: 0 0 auto; }

/*
 * ⚠️ QUIET, NOT HIDDEN.
 *
 * Update bag only matters without JavaScript, but hiding it entirely would make
 * quantity changes unsaveable for anyone in that position. It reads as a link
 * so it never competes with Checkout.
 */
.x-cart__update {
  border: 0;
  background: none;
  padding: 0;
  font-size: 0.8125rem;
  color: var(--x-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.x-cart__update:hover { color: var(--x-ink); }
.x-cart__update[disabled] { opacity: 0.45; cursor: default; }

.x-cart__continue {
  display: inline-block;
  /* It sits above the items now, so the space belongs underneath it. */
  margin: 0 0 0.875rem;
  font-size: 0.8125rem;
  color: var(--x-muted);
}

.x-cart__continue:hover { color: var(--x-ink); }

@media (min-width: 1024px) {
  .x-cart__aside { position: sticky; top: 6rem; }
}

/* ── Summary panel, shared by the bag and checkout ────────────────────────── */

.x-sum,
.woocommerce .cart_totals {
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  background: var(--x-surface-warm);
  padding: clamp(1.125rem, 2.5vw, 1.5rem);
}

.x-sum__title,
.cart_totals .x-sum__title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  margin: 0 0 0.875rem;
}

.x-sum__line,
.x-review__totals .x-sum__line,
.woocommerce .cart_totals table.shop_table tr:not(.order-total) {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.3125rem 0;
  font-size: 0.8125rem;
  color: var(--x-muted);
}

.x-sum__line > span:last-child,
.woocommerce .cart_totals table.shop_table tr:not(.order-total) > td {
  color: var(--x-ink-soft);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.x-sum__line.is-saving > span,
.x-sum__line.is-saving .amount { color: var(--x-success); font-weight: 500; }

.x-sum__drop {
  margin-left: 0.25rem;
  color: var(--x-muted);
  text-decoration: none;
  font-size: 0.875rem;
}

.x-sum__drop:hover { color: var(--x-danger); }

/*
 * ⚠️ THE LEGACY SHIPPING RULES LIVED HERE AND BROKE THE ROW'S ALIGNMENT.
 *
 * They styled WooCommerce's default markup, where the shipping block is a table
 * row, by making `.woocommerce-shipping-totals` itself a flex row. `cart-shipping.php`
 * now renders that element as a container holding an `.x-sum__line`, so the old
 * rule turned the container into a flex row and its children into flex items —
 * the label and the amount ended up side by side at the left instead of pushed
 * apart, while every other row in the panel aligned correctly.
 *
 * Same failure as the `:has(.cart-collaterals)` grid: CSS written for markup
 * that no longer exists, still matching because the class name survived.
 */

.x-sum__total,
.x-review__totals .x-sum__total,
.woocommerce .cart_totals table.shop_table tr.order-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.625rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--x-line-strong);
  font-size: 0.875rem;
  color: var(--x-ink);
}

.x-sum__total strong,
.x-review__totals .x-sum__total strong,
.woocommerce .cart_totals table.shop_table tr.order-total td {
  font-size: 1.375rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* The tax breakdown WooCommerce appends inside the total — kept, but demoted so
   it stops competing with the figure it annotates. */
.x-sum__total small,
.x-review__totals .x-sum__total small {
  display: block;
  font-size: 0.6875rem;
  font-weight: 400;
  color: var(--x-muted);
  letter-spacing: 0;
  margin-top: 0.125rem;
}

.x-sum .wc-proceed-to-checkout { margin-top: 1rem; padding: 0; }

.x-sum .wc-proceed-to-checkout .checkout-button {
  display: block;
  width: 100%;
  text-align: center;
}

.x-sum__trust {
  list-style: none;
  margin: 0.875rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.375rem;
}

.x-sum__trust li {
  position: relative;
  padding-left: 1.125rem;
  font-size: 0.75rem;
  color: var(--x-muted);
}

.x-sum__trust li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.4375rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--x-r-pill);
  background: var(--x-success);
  opacity: 0.6;
}

/* ────────────────────────────────────────────────────────────────────────────
 * Checkout — order review
 * ──────────────────────────────────────────────────────────────────────────── */

.x-review {
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  background: var(--x-surface-warm);
  padding: clamp(1.125rem, 2.5vw, 1.5rem);
}

.x-review__items {
  list-style: none;
  margin: 0 0 0.875rem;
  padding: 0 0 0.875rem;
  border-bottom: 1px solid var(--x-line);
  display: grid;
  gap: 0.875rem;
}

.x-review__item {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
}

/*
 * ⚠️ THE ROUNDING LIVES ON THE IMAGE, NOT ON THIS WRAPPER.
 *
 * `overflow: hidden` here is the obvious way to round the thumbnail, and it
 * silently ate the quantity badge: the badge is positioned at -0.375rem to sit
 * ON the corner, which puts it outside the box that was clipping. The result
 * was a dark sliver where "2" should be — the number simply gone, on the one
 * element whose entire job is saying how many.
 */
.x-review__thumb {
  position: relative;
  display: block;
  width: 3rem;
  height: 3rem;
  flex: none;
  background: var(--x-surface);
  border-radius: var(--x-r-sm);
}

.x-review__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: var(--x-r-sm);
}

/* The quantity rides on the image so a long product name is not truncated to
   make room for "× 1". */
/* ⚠️ NOTHING RENDERS THIS ANY MORE — the quantity moved out of the thumbnail
   and next to the product name as "× 2". See the note in review-order.php.
   Kept because the badge is the obvious thing to reach for again, and the
   border trick below is the non-obvious part of making one work. */
.x-review__count {
  position: absolute;
  top: -0.4rem;
  right: -0.4rem;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.3rem;
  box-sizing: border-box;
  /* Separates the badge from whatever it overlaps, at any thumbnail. */
  border: 2px solid var(--x-surface-warm);
  display: grid;
  place-items: center;
  border-radius: var(--x-r-pill);
  background: var(--x-dark);
  color: var(--x-bg);
  font-size: 0.6875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.x-review__name {
  font-size: 0.8125rem;
  line-height: 1.35;
  color: var(--x-ink);
  min-width: 0;   /* lets the title truncate instead of pushing the price out */
}

/*
 * ⚠️ `min-width: 0` ON BOTH LEVELS, OR THE ELLIPSIS NEVER APPEARS.
 *
 * A grid/flex item defaults to `min-width: auto`, which means "never shrink
 * below my content". Without it on the row, the wrapper AND the title, a long
 * product name silently widens the column and shoves the price off the card
 * instead of truncating.
 */
.x-review__nameline {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  min-width: 0;
}

.x-review__title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.x-review__qty {
  flex: none;
  color: var(--x-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.x-review__money {
  font-size: 0.875rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.05rem;
}

/*
 * MRP above the price actually charged.
 *
 * ⚠️ STACKED, NOT SIDE BY SIDE. The row is a three-column grid whose last
 * column sizes to its content, so putting two prices on one line steals width
 * from the product name — the name would truncate earlier to make room for a
 * number that is crossed out. Stacking keeps the struck price out of the name's
 * way entirely.
 */
.x-review__money del {
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--x-muted);
  text-decoration-thickness: 1px;
}
.x-review__money ins {
  text-decoration: none;
  background: none;
  color: inherit;
}

/* ── Shipping calculator ──────────────────────────────────────────────────── */

/*
 * ⚠️ WOOCOMMERCE RELIES ON ITS OWN STYLESHEET TO HIDE THIS, AND WE DEQUEUE IT.
 *
 * The calculator is always in the markup and is meant to be revealed by the
 * "Change address" toggle. Without `woocommerce-general` loaded, nothing hid it
 * — so every country in the world and every Indian state rendered inline in the
 * middle of the order summary. Woo's own cart script still does the toggling;
 * it only needed the closed state back.
 */
.shipping-calculator-form { display: none; }
.shipping-calculator-form.is-open { display: block; }

.x-sum .shipping-calculator-form,
.x-review__totals .shipping-calculator-form {
  margin-top: 0.625rem;
  padding-top: 0.625rem;
  border-top: 1px solid var(--x-line);
}

.x-sum .shipping-calculator-form p { margin: 0 0 0.5rem; }

.x-sum .shipping-calculator-form input,
.x-sum .shipping-calculator-form select,
.x-sum .shipping-calculator-form .select2-selection {
  width: 100%;
  height: 2.375rem;
  padding: 0 0.75rem;
  font-size: 0.8125rem;
  color: var(--x-ink);
  background: var(--x-white);
  border: 1px solid var(--x-line-strong);
  border-radius: var(--x-r-sm);
}

.x-sum .shipping-calculator-form button {
  width: 100%;
  margin-top: 0.25rem;
}

/* ── Bag quantity stepper ─────────────────────────────────────────────────── */

.x-qtybox {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.1875rem;
  border: 1px solid var(--x-line-strong);
  border-radius: var(--x-r-pill);
  background: var(--x-white);
}

.x-qtybox__step {
  width: 1.875rem;
  height: 1.875rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--x-r-pill);
  background: transparent;
  color: var(--x-ink);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.x-qtybox__step:hover { background: var(--x-surface); }
.x-qtybox__step:focus-visible { outline: 2px solid var(--x-dark); outline-offset: 1px; }

.x-qtybox__n {
  width: 2.25rem;
  height: 1.875rem;
  padding: 0;
  text-align: center;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  color: var(--x-ink);
  background: transparent;
  border: 0;
  /*
   * ⚠️ THE NATIVE SPINNERS ARE REMOVED ON PURPOSE.
   * They sit inside the pill, are a few pixels tall, and duplicate the − and +
   * either side of them — two controls for one job, one of them unusable.
   */
  -moz-appearance: textfield;
  appearance: textfield;
}

.x-qtybox__n::-webkit-outer-spin-button,
.x-qtybox__n::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.x-qtybox__n:focus-visible { outline: 2px solid var(--x-dark); outline-offset: 1px; border-radius: var(--x-r-pill); }

/* Held while the page reloads, so a second press cannot queue a second update. */
.x-qtybox.is-busy { opacity: 0.55; pointer-events: none; }

/* ── Shipping block in the summary ───────────────────────────────────────── */

.x-ship { display: block; }
.x-ship__to,
.x-ship__contents {
  margin: 0.125rem 0 0;
  font-size: 0.75rem;
  color: var(--x-muted);
}
.x-ship__calc { margin: 0.25rem 0 0; }
.x-ship__calc .shipping-calculator-button {
  font-size: 0.75rem;
  color: var(--x-ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.x-ship__calc .shipping-calculator-button:hover { color: var(--x-ink); }
.x-ship ul#shipping_method { list-style: none; margin: 0; padding: 0; text-align: right; }

/* ── Several delivery options ────────────────────────────────────────────── */
/*
 * See the note in cart-shipping.php: with more than one rate the two-column
 * summary row becomes a block so the choices get the full card width.
 */
.x-ship--choices .x-sum__line {
  display: block;
  padding-bottom: 0.25rem;
}
.x-ship--choices .x-sum__line > span:first-child {
  display: block;
  margin-bottom: 0.5rem;
}
.x-ship--choices .x-sum__line > span:last-child {
  display: block;
  text-align: left;
}

.x-ship--choices ul#shipping_method,
.woocommerce .cart_totals tr.woocommerce-shipping-totals ul#shipping_method {
  display: grid;
  gap: 0.5rem;
  text-align: left;
}

/*
 * ⚠️ THE PADDING BELONGS TO THE ROW, NOT THE LABEL.
 *
 * With `padding-block` on the label, the label's first line started 5px lower
 * than the radio beside it — so on a one-line option the radio sat visibly
 * above the middle of its own text, and the two rows looked unaligned. The row
 * carries the padding now, so the radio and the first line of the label share a
 * top edge and the radio reads as centred on the line it belongs to.
 *
 * `flex-start`, not `center`: on the two-line option the radio must sit against
 * the FIRST line, not float to the middle of the block.
 */
.x-ship--choices ul#shipping_method li,
.woocommerce .cart_totals table.shop_table tr.woocommerce-shipping-totals ul#shipping_method li {
  display: flex;
  /* ⚠️ CENTRED, NOT TOP-ALIGNED.
     A rate whose name wraps to two lines left the radio pinned to the first,
     sitting high against a two-line block. The control belongs beside the whole
     label, not beside its first line. */
  align-items: center;
  gap: 0.625rem;
  margin: 0;
  padding-block: 0.3125rem;
}

/*
 * ⚠️ THE NATIVE RADIO IS RESTYLED, NOT HIDDEN — same reasoning as the payment
 * methods. `appearance: none` on the real input keeps its focus handling,
 * keyboard behaviour and for/id pairing; a hidden input with a fake span beside
 * it loses all three. The default was painting system blue into a cream page.
 */
.x-ship--choices input.shipping_method,
.woocommerce .cart_totals tr.woocommerce-shipping-totals input.shipping_method {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  /* The label's first line box is 13px x 1.45 = 18.85px against an 18px radio,
     so sharing a top edge centres it to within half a pixel. No nudge needed —
     a margin here is what threw the alignment out before. */
  margin: 0;
  border: 1.5px solid var(--x-line-strong);
  border-radius: var(--x-r-pill);
  background: var(--x-surface);
  cursor: pointer;
  transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
}
.x-ship--choices input.shipping_method:hover,
.woocommerce .cart_totals tr.woocommerce-shipping-totals input.shipping_method:hover { border-color: var(--x-dark); }
.x-ship--choices input.shipping_method:checked,
.woocommerce .cart_totals tr.woocommerce-shipping-totals input.shipping_method:checked {
  border-color: var(--x-dark);
  background: var(--x-dark);
  box-shadow: inset 0 0 0 3px var(--x-surface);
}
.x-ship--choices input.shipping_method:focus-visible,
.woocommerce .cart_totals tr.woocommerce-shipping-totals input.shipping_method:focus-visible {
  outline: 2px solid var(--x-dark);
  outline-offset: 2px;
}

/*
 * ⚠️ FLEX ONLY WORKS BECAUSE THE TEMPLATE EMITS TWO ELEMENTS.
 *
 * WooCommerce's own label is a single string — name, colon, space, price — and
 * making that a flex container turns the text node and the price span into
 * separate flex items, DISCARDING the whitespace between them: the row rendered
 * as "Hand delivery by our co-founder:₹999.00". cart-shipping.php now emits an
 * explicit .x-ship__name and .x-ship__cost, so the gap is set here rather than
 * depending on a space character surviving layout.
 */
.x-ship--choices ul#shipping_method label,
.woocommerce .cart_totals tr.woocommerce-shipping-totals ul#shipping_method label {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--x-ink);
  cursor: pointer;
}

.x-ship--choices .x-ship__name,
.woocommerce .cart_totals tr.woocommerce-shipping-totals .x-ship__name { min-width: 0; }

/* Right-aligned in a column so two options can be compared at a glance rather
   than read — the same treatment every other figure in this summary gets. */
.x-ship--choices .x-ship__cost,
.woocommerce .cart_totals tr.woocommerce-shipping-totals .x-ship__cost {
  flex: none;
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ────────────────────────────────────────────────────────────────────────────
 * Pay for order
 * ──────────────────────────────────────────────────────────────────────────── */

/*
 * Deliberately the same card as the Partial COD confirmation: they are the same
 * moment in the journey, and two different-looking payment screens in one shop
 * reads as one of them being a phishing page.
 */
.x-pay {
  display: flex;
  justify-content: center;
  padding: clamp(2rem, 8vw, 5rem) 1.25rem;
}

.x-pay__card {
  width: 100%;
  max-width: 30rem;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.5rem, 4vw, 2rem);
}

.x-pay__title {
  font-family: var(--font-display);
  font-size: clamp(1.375rem, 3.5vw, 1.75rem);
  line-height: 1.2;
  margin: 0 0 0.5rem;
}

.x-pay__lead {
  margin: 0 0 1.25rem;
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--x-ink-soft);
}

.x-pay__rows { border-top: 1px solid var(--x-line); margin-bottom: 1.25rem; }

.x-pay__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6875rem 0;
  border-bottom: 1px solid var(--x-line);
  font-size: 0.9375rem;
}

/* ⚠️ The label does not wrap; the value does.
   "Paying by" against "UPI, Cards, NetBanking" broke both halves onto two lines
   at 320px, and a two-line label opposite a two-line value stopped reading as a
   row at all. The label is always short, so it keeps its line and the value
   takes the wrapping. */
.x-pay__row > span:first-child { color: var(--x-muted); white-space: nowrap; }
.x-pay__row > span:last-child { text-align: right; min-width: 0; }
.x-pay__row > span:last-child { font-weight: 600; font-variant-numeric: tabular-nums; }
.x-pay__row.is-quiet { font-size: 0.8125rem; }
.x-pay__row.is-quiet > span:last-child { font-weight: 400; color: var(--x-ink-soft); }

/*
 * ⚠️ THE GATEWAY'S BUTTON IS STYLED WHERE IT LANDS, NOT REPLACED.
 * Razorpay renders its own form and button through the receipt action; taking
 * it over would break the handover, so we only restyle what it prints.
 */
/*
 * ⚠️ TARGETED BY RAZORPAY'S OWN IDs.
 *
 * The plugin prints `<button id="btn-razorpay">` and
 * `<button id="btn-razorpay-cancel">` — plain buttons with no classes and no
 * `type="submit"`, which is why a selector written against submit inputs
 * matched nothing and they rendered as raw browser controls.
 */
/* ⚠️ `.x-pay__btn` IS IN HERE BECAUSE THE PARTIAL COD BUTTON IS `type="button"`.
   It opens the Razorpay modal from JS rather than submitting anything, so it
   matched none of the selectors below and kept its intrinsic width — a button
   that hugged its label on one pay screen and spanned the card on the other. */
.x-pay__card #btn-razorpay,
.x-pay__card .x-pay__btn,
.x-pay__card button[type="submit"],
.x-pay__card input[type="submit"] {
  display: block;
  width: 100%;
  padding: 0.9375rem 1.25rem;
  border: 0;
  border-radius: var(--x-r-pill);
  background: var(--x-dark);
  color: var(--x-bg);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
}

.x-pay__card input[type="submit"]:hover,
.x-pay__card button[type="submit"]:hover { opacity: 0.9; }

/* Razorpay also prints a "Cancel" link beside its button. */
.x-pay__card #btn-razorpay-cancel,
.x-pay__card a.button.cancel {
  display: inline-block;
  margin-top: 0.75rem;
  font-size: 0.8125rem;
  color: var(--x-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  background: none;
  border: 0;
  padding: 0;
}

/* Razorpay wraps its two buttons in a bare <p>; stack them, don't inline. */
.x-pay__card p:has(#btn-razorpay) { display: flex; flex-direction: column; align-items: stretch; gap: 0; margin: 0; }
.x-pay__card #btn-razorpay-cancel { align-self: center; cursor: pointer; }

/*
 * ⚠️ THE BUTTON IS ALREADY DISABLED — IT JUST DID NOT LOOK IT.
 *
 * Razorpay's script.js calls `setDisabled('btn-razorpay')` the moment the
 * payment modal opens, and disables the cancel button once a payment succeeds
 * and the form is being submitted. Because nothing here styled `[disabled]`,
 * both kept their full black "Pay Now" treatment while the payment was already
 * going through — so the page invited a second click at exactly the moment a
 * second click is most alarming.
 *
 * Attribute selector, not `:disabled`: the plugin sets the attribute directly
 * via `setAttribute('disabled', true)`, and matching what it actually writes is
 * what makes this hold.
 */
.x-pay__card #btn-razorpay[disabled] {
  background: var(--x-muted) !important;
  color: var(--x-bg) !important;
  cursor: progress;
  opacity: 0.65;
}
.x-pay__card #btn-razorpay[disabled]:hover { background: var(--x-muted) !important; }
.x-pay__card #btn-razorpay-cancel[disabled] {
  opacity: 0.35;
  pointer-events: none;
  cursor: default;
}

/* Razorpay's "Please wait while we are processing your payment." — the active
   state once the button has gone quiet, so something on the page still moves. */
.x-pay__card #msg-razorpay-success {
  border: 1px solid var(--x-line-strong);
  border-left: 3px solid var(--x-success);
  border-radius: var(--x-r-sm);
  background: var(--x-bg-alt);
  color: var(--x-ink);
  font-size: 0.8125rem;
  padding: 0.85rem 1rem;
  margin: 0 0 1rem;
}
.x-pay__card p { font-size: 0.875rem; color: var(--x-ink-soft); }

.x-pay__safe {
  margin: 1rem 0 0;
  font-size: 0.75rem !important;
  color: var(--x-muted) !important;
  text-align: center;
}

/*
 * ⚠️ `/checkout/order-pay/` IS A THIRD PAY SCREEN, AND IT IS WOOCOMMERCE'S.
 *
 * Two of the three are ours: the Partial COD page and `order-receipt.php` both
 * print `.x-pay__card` markup. This one does not — the endpoint renders
 * WooCommerce's own `checkout/form-pay.php`, which we do not override, so the
 * only lever is CSS. Everything below reproduces the card above on markup that
 * is `form#order_review > table.shop_table + div#payment`.
 *
 * ⚠️ `#order_review` IS A `<form>` HERE AND A `<div>` ON THE CHECKOUT.
 *
 * That is why the checkout's review-panel rules are all written
 * `div#order_review#order_review` — without the `div` they matched this form
 * too and dressed it in the checkout aside's green panel. Do not drop it.
 *
 * ⚠️ AND THE GENERIC TABLE RULES REACH IT.
 *
 * `.woocommerce table.shop_table` gives it a card of its own, styles every
 * `<th>` as an uppercase column header on a grey fill, and below 768px stacks
 * each row into a `data-title` label above its value. Written for the cart, and
 * correct there. Here it produced the grey label blocks with the amount
 * stranded on the line beneath. Each is undone explicitly rather than by
 * lowering the cart's rules, which are still doing their job on the cart.
 */
/*
 * ⚠️ `:has(form#order_review)` — `/checkout/order-pay/` RENDERS TWO DIFFERENT
 * PAGES AT THE SAME URL, AND ONLY ONE OF THEM NEEDS THIS.
 *
 * With no payment method chosen the endpoint renders `form-pay.php`, the bare
 * table this whole block dresses as a card. Once a gateway is chosen it renders
 * `order-receipt.php` instead — our own template, which already prints
 * `.x-pay__card`. Unqualified, these rules carded that too, so the receipt
 * appeared as a card inside a card: two borders, two lots of padding, and at
 * 320px the doubled padding wrapped the title and every row label.
 *
 * The presence of the form is the difference between the two, so it is what the
 * selector asks about.
 */
/* Matched to `.x-pay` deliberately: 30rem card + its 1.25rem gutter, so all three
   pay screens put their card on the same left edge at the same width. The
   container's own gutter is narrower at 320px and put this card 7px wider and
   7px further left than the other two. */
body.woocommerce-order-pay .x-container:has(form#order_review) {
  max-width: 32.5rem;
  padding-inline: 1.25rem;
  padding-block: clamp(2rem, 8vw, 5rem);
}

/*
 * ⚠️ THE CARD IS `div.woocommerce`, NOT THE FORM.
 *
 * The heading comes from `before_woocommerce_pay_form`, which fires inside the
 * shortcode's wrapper and outside the form. Carding the form instead put the
 * title above the card, orphaned on the page background.
 */
body.woocommerce-order-pay .x-container > .woocommerce:has(form#order_review) {
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.5rem, 4vw, 2rem);
}

/*
 * ⚠️ THE RECEIPT CARD SITS INSIDE `.x-container`; THE PARTIAL COD ONE DOES NOT.
 *
 * `order-receipt.php` renders through `woocommerce.php`, so its `.x-pay` is
 * wrapped in the page container and inherits its inline padding on top of
 * `.x-pay`'s own. The Partial COD page prints `.x-pay` straight into the body.
 * Same card, two different widths — 254px against 280px at a 320px viewport,
 * which is exactly the width where a card losing 26px starts wrapping rows that
 * fit on the other page. The container stands down where `.x-pay` handles it.
 */
body.woocommerce-order-pay .x-container:has(.x-pay) {
  max-width: none;
  padding-inline: 0;
}

/* The card carries the padding now. Left on the form it inset the table and the
   payment tiles 16px further than the heading above them, so nothing in the
   card shared a left edge. */
body.woocommerce-order-pay form#order_review { padding: 0; background: none; }

/* The card is the border now; the table inside it must not draw a second one. */
body.woocommerce-order-pay form#order_review table.shop_table {
  border: 0;
  border-radius: 0;
  background: none;
  margin: 0 0 1.25rem;
}

/* "Product / Qty / Totals" over a single line item is a header for a table that
   isn't one — the row reads on its own, as it does on the other two screens. */
body.woocommerce-order-pay form#order_review table.shop_table thead { display: none; }

/* Every row — line item and totals alike — becomes an `.x-pay__row`. */
body.woocommerce-order-pay form#order_review table.shop_table tr {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6875rem 0;
  border-bottom: 1px solid var(--x-line);
}

body.woocommerce-order-pay form#order_review table.shop_table tbody tr { border-top: 1px solid var(--x-line); }
body.woocommerce-order-pay form#order_review table.shop_table tfoot tr:last-child { border-bottom: 0; }

/* ⚠️ `display` IS IN HERE ON PURPOSE.
   Below 768px the cart rules make every `td` a `space-between` flex row so its
   `data-title` sits opposite the value. With the label gone that only had one
   effect left: it pushed the "(includes ₹152.39 IGST)" note out to the right
   edge alongside the total instead of under it. */
body.woocommerce-order-pay form#order_review table.shop_table th,
body.woocommerce-order-pay form#order_review table.shop_table td {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  font-size: 0.9375rem;
  text-align: left;
}

/* Undoes the uppercase grey column-header treatment on the totals labels. */
body.woocommerce-order-pay form#order_review table.shop_table th {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.9375rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--x-muted);
}

body.woocommerce-order-pay form#order_review table.shop_table td.product-total,
body.woocommerce-order-pay form#order_review table.shop_table td.product-subtotal {
  margin-left: auto;
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* WooCommerce prints the tax note inside the Total cell; it must not carry the
   amount's weight or push the row onto two lines. */
body.woocommerce-order-pay form#order_review table.shop_table td small {
  display: block;
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--x-muted);
}

body.woocommerce-order-pay form#order_review table.shop_table td.product-name {
  flex: 1 1 auto;
  font-weight: 500;
}

body.woocommerce-order-pay form#order_review table.shop_table td.product-quantity { color: var(--x-muted); }

/* ⚠️ The mobile stacking rules put the label back as generated content. */
body.woocommerce-order-pay form#order_review table.shop_table td::before { content: none; }

body.woocommerce-order-pay form#order_review #payment { background: none; padding: 0; }

/* Reuses the card's button treatment for `#place_order`, which is the same
   control as the other two screens' pay button and should not look different. */
body.woocommerce-order-pay form#order_review #place_order {
  display: block;
  width: 100%;
  margin-top: 0.5rem;
  padding: 0.9375rem 1.25rem;
  border: 0;
  border-radius: var(--x-r-pill);
  background: var(--x-dark);
  color: var(--x-bg);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
}

body.woocommerce-order-pay form#order_review #place_order:hover { opacity: 0.9; }

/* ────────────────────────────────────────────────────────────────────────────
 * Order received
 * ──────────────────────────────────────────────────────────────────────────── */

.x-done {
  max-width: 44rem;
  margin: 0 auto;
  padding: clamp(1.5rem, 5vw, 3rem) 1.25rem clamp(3rem, 8vw, 5rem);
  display: grid;
  gap: clamp(1rem, 3vw, 1.5rem);
}

.x-done__card {
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  text-align: center;
}

.x-done__tick {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  margin: 0 auto 1rem;
  border-radius: var(--x-r-pill);
  background: color-mix(in srgb, var(--x-success) 14%, var(--x-white));
  color: var(--x-success);
}

.x-done__card.is-failed .x-done__title { color: var(--x-danger); }

.x-done__title {
  font-family: var(--font-display);
  font-size: clamp(1.625rem, 4.5vw, 2.25rem);
  line-height: 1.15;
  margin: 0 0 0.5rem;
}

.x-done__lead {
  margin: 0 auto 1.5rem;
  max-width: 30rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--x-ink-soft);
}

/* The two facts someone actually needs if they contact us. */
.x-done__ref {
  display: flex;
  justify-content: center;
  gap: clamp(1.5rem, 6vw, 3rem);
  padding: 1rem 0;
  margin-bottom: 1.25rem;
  border-block: 1px solid var(--x-line);
}

/*
 * ⚠️ DIRECT CHILD ONLY — `.x-done__ref span` MATCHED THE CURRENCY SYMBOL TOO.
 *
 * This rule exists to stack the little uppercase label above its value. Written
 * as a descendant selector it also caught WooCommerce's nested
 * `<span class="woocommerce-Price-currencySymbol">₹</span>`, turning it into a
 * block — which puts the ₹ on its own line with the digits underneath, no
 * matter what `white-space` is set to. That was the real cause of the broken
 * "PAID ₹592.05"; nowrap alone could never have fixed it.
 */
.x-done__ref > div > span {
  display: block;
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--x-muted);
  margin-bottom: 0.25rem;
}
/* Whatever markup wc_price() produces, the amount stays one inline run. */
.x-done__ref strong span,
.x-done__ref strong bdi { display: inline; white-space: nowrap; }

/*
 * ⚠️ `wc_price()` PUTS THE CURRENCY SYMBOL IN ITS OWN `<span>`.
 *
 * The markup is `<span>₹</span>592.05`, so a narrow flex column is free to
 * break between them — which is exactly what happened: "₹" sat on one line and
 * "592.05" on the next, under a heading reading PAID. `nowrap` keeps an amount
 * as one word, and `flex: 0 0 auto` stops the columns being squeezed that
 * narrow in the first place.
 */
.x-done__ref > div { flex: 0 0 auto; text-align: center; }
.x-done__ref strong {
  display: block;
  font-size: 1.125rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.x-done__ref strong .woocommerce-Price-amount { white-space: nowrap; }

.x-done__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.625rem;
}

.x-done__panel {
  background: var(--x-surface-warm);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.25rem, 3.5vw, 1.75rem);
}

.x-done__h2 { font-family: var(--font-display); font-size: 1.25rem; margin: 0 0 1rem; }

.x-done__items { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: 0.875rem; }

.x-done__item {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
}

.x-done__thumb {
  position: relative;
  width: 3rem;
  height: 3rem;
  flex: none;
  background: var(--x-surface);
  border-radius: var(--x-r-sm);
}

.x-done__thumb img { width: 100%; height: 100%; object-fit: cover; display: block;   border-radius: var(--x-r-sm);
}


.x-done__name { font-size: 0.875rem; line-height: 1.35; }
/* "× 2" belongs to the product name but is not part of it. */
.x-done__qty { color: var(--x-ink-soft); white-space: nowrap; }
.x-done__money { font-size: 0.875rem; font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }

.x-done__totals { border-top: 1px solid var(--x-line); padding-top: 0.75rem; }

/* Partial COD: what is still owed is the one number to remember, so it is the
   loudest thing in the block after the order total. */
.x-done__due > span:last-child { font-weight: 600; color: var(--x-accent); }
.x-done__duenote {
  margin: 0.5rem 0 0;
  font-size: 0.75rem;
  color: var(--x-ink-soft);
}

.x-done__meta {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--x-line);
}

@media (min-width: 560px) { .x-done__meta { grid-template-columns: 1.3fr 1fr; } }

.x-done__meta h3 {
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--x-muted);
  margin: 0 0 0.5rem;
  font-weight: 600;
}

.x-done__meta address,
.x-done__meta p {
  font-style: normal;
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--x-ink-soft);
}

.x-done__quiet { color: var(--x-muted) !important; font-size: 0.8125rem !important; }

/* WooCommerce's own overview and table are replaced by the markup above. */
.x-done .woocommerce-order-overview,
.x-done .woocommerce-order-details__title,
.x-done table.woocommerce-table--order-details,
.x-done .woocommerce-customer-details > h2,
.x-done .woocommerce-columns--addresses { display: none; }

/* ────────────────────────────────────────────────────────────────────────────
 * Bag: "Cart updated" as a toast
 * ──────────────────────────────────────────────────────────────────────────── */

/*
 * ⚠️ THE POINT IS THAT IT TAKES NO SPACE, NOT THAT IT LOOKS LIKE A TOAST.
 *
 * Updating a quantity reloads the bag, and WooCommerce prints "Cart updated."
 * as a block at the top of the page. That block pushes the ladder, the items and
 * the summary down by its own height — so every press of + or − visibly shoved
 * the thing being pressed down the screen, and the second press landed
 * somewhere else. That is the flicker.
 *
 * `position: fixed` removes it from the flow entirely, so the page reloads with
 * the item card in exactly the same place it was.
 *
 * ⚠️ ANCHORED TO THE BOTTOM, NOT THE TOP.
 *
 * The header is `position: sticky; z-index: 50`. A toast at the top either sits
 * under it or covers the logo and menu; at the bottom it collides with nothing,
 * and on a phone it is nearer the thumb that just pressed the button.
 *
 * ⚠️ ONLY THE SUCCESS NOTICE. Errors stay inline, in the flow, where they cannot
 * time out before they are read — an error usually needs an action, and a
 * message that removes itself is the wrong shape for that.
 */
body.woocommerce-cart .woocommerce-notices-wrapper { margin: 0; }

body.woocommerce-cart .woocommerce-notices-wrapper .woocommerce-message {
  position: fixed;
  left: 50%;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  z-index: 70;
  width: max-content;
  max-width: min(24rem, calc(100vw - 2rem));
  margin: 0;
  /*
   * ⚠️ `!important` IS REQUIRED HERE, AND ONLY ON THESE THREE.
   *
   * xl-checkout-theme.php also loads on the bag (it enqueues for is_cart() as
   * well as is_checkout()) and sets, for every notice:
   *
   *     background: var(--x-surface) !important;
   *     padding: 1rem 1.25rem !important;
   *     border-top-width: 1px !important;
   *
   * An important declaration beats a normal one whatever the specificity or
   * source order, so without matching it the toast rendered as a white panel
   * with pale text — invisible against the page it floats over. Everything else
   * below wins on ordinary cascade rules and is deliberately left alone.
   */
  padding: 0.75rem 1.125rem !important;
  border: 0;
  border-top-width: 0 !important;
  border-radius: var(--x-r-md);
  background: var(--x-dark) !important;
  color: var(--x-bg);
  font-size: 0.8125rem;
  line-height: 1.4;
  box-shadow: 0 6px 24px rgba(32, 31, 28, 0.22);
  animation: x-toast 4.5s both;
}

/* WooCommerce puts a "Continue shopping" button inside this notice; the bag
   already has that link, and a button inside a toast that is about to vanish is
   a target nobody can rely on hitting. */
body.woocommerce-cart .woocommerce-notices-wrapper .woocommerce-message .button {
  display: none;
}

@keyframes x-toast {
  0%        { opacity: 0; transform: translate(-50%, 0.75rem); }
  6%, 82%   { opacity: 1; transform: translate(-50%, 0); }
  100%      { opacity: 0; transform: translate(-50%, 0.75rem); visibility: hidden; }
}

/*
 * ⚠️ REDUCED MOTION STILL MEANS IT GOES AWAY.
 *
 * The preference is about movement, not about leaving a message on screen
 * forever — so the slide is dropped and the fade and the dismissal are kept.
 */
@media (prefers-reduced-motion: reduce) {
  body.woocommerce-cart .woocommerce-notices-wrapper .woocommerce-message {
    animation: x-toast-fade 4.5s both;
  }
  @keyframes x-toast-fade {
    0%      { opacity: 0; transform: translateX(-50%); }
    6%, 82% { opacity: 1; transform: translateX(-50%); }
    100%    { opacity: 0; transform: translateX(-50%); visibility: hidden; }
  }
}


/* ────────────────────────────────────────────────────────────────────────────
 * Product description blocks
 * ──────────────────────────────────────────────────────────────────────────── */

/*
 * Styles the markup inside product descriptions written by xl-product-copy.php.
 *
 * ⚠️ THEY LIVE HERE, NOT IN THAT PLUGIN, SO THE PLUGIN IS DISPOSABLE.
 *
 * The descriptions themselves are copied into the database when the plugin's
 * button is pressed, so the words survive the plugin being removed — but the
 * layout would not if these rules travelled with it. Keeping them in the theme
 * means the plugin is a one-shot writer that can be deleted once all twelve
 * products are written, with nothing visual depending on it.
 */
.x-pdp__lead { font-size: 1rem; }

/*
 * ⚠️ THE FACTS BLOCK IS A LIST, NOT A TABLE.
 *
 * A two-column table is the obvious markup and the wrong one: at 320px a label
 * like "Best before" and its value cannot share a row without one of them
 * wrapping badly or the table forcing a sideways scroll. A wrapping flex row
 * stacks cleanly and needs no scroll container.
 */
.x-pdp__facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}
.x-pdp__facts li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--x-line, #e1dace);
  font-size: 0.875rem;
}
.x-pdp__facts li:last-child { border-bottom: 0; }
.x-pdp__facts li span {
  flex: 0 0 8rem;
  color: var(--x-muted, #8C8579);
}

/* The INCI list is reference text, not reading text — smaller and allowed to be
   dense, but never below the 13px floor used everywhere else. */
.x-pdp__inci {
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--x-ink-soft, #6f6a5e);
  word-break: break-word;
}


/* ════════════════════════════════════════════════════════════════════════════
 * The cart summary, now that WooCommerce renders it
 *
 * ⚠️ THE SELECTORS ABOVE WERE EXTENDED, NOT DUPLICATED.
 *
 * `cart/cart-totals.php` and `cart/cart-shipping.php` are handed back, so this
 * block is a `<table>` on the cart and still the design's `<div>`s on the
 * checkout, which keeps its own `review-order.php`. Writing a second set of rules
 * for the table would let the two summaries drift apart — the one thing the
 * shared `.x-sum` naming existed to prevent — so WooCommerce's row selectors were
 * added to the rule blocks that already style the checkout's rows instead.
 *
 * What is left here is only what a table needs and a div does not.
 * ════════════════════════════════════════════════════════════════════════════ */

.woocommerce .cart_totals table.shop_table {
  /* The table is a layout the design does not use; the rows are the design. */
  width: 100%;
  border: 0;
  margin: 0;
  border-collapse: collapse;
}

.woocommerce .cart_totals table.shop_table th,
.woocommerce .cart_totals table.shop_table td {
  /* woocommerce.css gives cells a surface colour and borders meant for a bordered
     table; against this card they drew boxes around every line. */
  background: none;
  border: 0;
  padding: 0;
  font-weight: inherit;
  text-align: left;
}

/* `display: flex` on a `<tr>` is what lets the label and figure sit at opposite
   ends, the same as a `.x-sum__line`. The cells become the two flex children. */
.woocommerce .cart_totals table.shop_table tr { width: 100%; }

/*
 * ⚠️ WOOCOMMERCE PRINTS ITS OWN "Cart totals" HEADING. THE DESIGN PRINTS
 * "Order summary" FROM `woocommerce_before_cart_totals`, SO CORE'S IS HIDDEN.
 *
 * Hidden rather than filtered away: the template prints it directly with no
 * filter, and taking the file over again for one line is what this whole exercise
 * is undoing.
 */
/* ⚠️ `:not(.x-sum__title)` IS LOAD-BEARING. `woocommerce_before_cart_totals`
   fires above core's heading, so the design's "Order summary" is also a direct
   `h2` child — and is printed FIRST. Without the exclusion this rule hid the
   design's title and left core's, which is the opposite of the intent. */
.woocommerce .cart_totals > h2:not(.x-sum__title) { display: none; }

/* Shipping is a row like any other; the label's two halves come from
   `xl_cart_shipping_label()`. */
.woocommerce .cart_totals tr.woocommerce-shipping-totals td { width: 100%; }
.woocommerce .cart_totals ul#shipping_method {
  list-style: none;
  margin: 0;
  padding: 0;
}
.woocommerce .cart_totals ul#shipping_method label {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
}

/* The destination line and the "enter your address" messages — the four that the
   old template dropped entirely and WooCommerce now prints again. */
.woocommerce .cart_totals .woocommerce-shipping-destination,
.woocommerce .cart_totals .woocommerce-shipping-contents {
  margin: 0.375rem 0 0;
  font-size: 0.75rem;
  color: var(--x-muted);
}


/*
 * ── The cart summary's remaining table-isms ──────────────────────────────────
 *
 * Everything above styles the rows through the same rule blocks the checkout's
 * `.x-sum` uses. These are the things a `<table>` brings that a `<div>` did not,
 * each one measured against the old override rather than guessed.
 */

/* ⚠️ THE TABLE DREW A WHITE CARD INSIDE THE CARD.
   `.woocommerce table.shop_table` carries a surface, a border and a radius meant
   for a bordered table on a plain page. Inside the summary card it painted a
   second rounded panel behind the rows. */
.woocommerce .cart_totals table.shop_table {
  background: none;
  border-radius: 0;
  box-shadow: none;
}

/* ⚠️ AND IT UPPERCASED EVERY LABEL.
   `.woocommerce table.shop_table th` is styled as a column header — 11px, 600,
   uppercase, letter-spaced. These are row labels, not headers: "SUBTOTAL" where
   the design says "Subtotal". */
.woocommerce .cart_totals table.shop_table th {
  font-size: inherit;
  font-weight: inherit;
  letter-spacing: normal;
  text-transform: none;
  color: inherit;
}

/* A negative fee is a saving and the design names it in green. The old template
   put `.is-saving` on the row; WooCommerce marks it `.fee`, and every fee this
   store adds is a discount. */
.woocommerce .cart_totals tr.fee th,
.woocommerce .cart_totals tr.fee td,
.woocommerce .cart_totals tr.cart-discount th,
.woocommerce .cart_totals tr.cart-discount td,
.woocommerce .cart_totals tr.fee .amount,
.woocommerce .cart_totals tr.cart-discount .amount {
  color: var(--x-success);
  font-weight: 500;
}

/*
 * ⚠️ THE SHIPPING ROW IS A BLOCK, NOT A TWO-COLUMN LINE.
 *
 * With more than one rate the choices need the card's full width — the label
 * sits on its own line and the options stack beneath it. This is what the old
 * template's `.x-ship--choices` class switched on; WooCommerce has no equivalent
 * class, so the row itself carries it.
 */
/* ⚠️ `table.shop_table` IS IN THESE SELECTORS ON PURPOSE.
   The row rule that makes every other line a flex pair is
   `.woocommerce .cart_totals table.shop_table tr:not(.order-total)` — (0,4,2).
   Without `table.shop_table` here this block is (0,3,1) and loses, which left
   the label and the options side by side in two narrow columns. */
.woocommerce .cart_totals table.shop_table tr.woocommerce-shipping-totals {
  display: block;
  padding-bottom: 0.25rem;
}
.woocommerce .cart_totals table.shop_table tr.woocommerce-shipping-totals > th {
  display: block;
  margin-bottom: 0.5rem;
}
.woocommerce .cart_totals table.shop_table tr.woocommerce-shipping-totals > td {
  display: block;
  text-align: left;
  width: 100%;
}

/* The line that says the total is goods-only until a pincode is given.
   See xl_cart_shipping_note(). */
/* ⚠️ THE ROW OPTS OUT OF THE FLEX TREATMENT THE OTHER ROWS GET.
   `.cart_totals table tr:not(.order-total)` makes every row a two-column flex
   pair; this one is a single full-width note and would otherwise be squeezed
   into the left column with an empty column beside it. */
.woocommerce .cart_totals table.shop_table tr.x-sum__noterow {
  display: block;
}
.woocommerce .cart_totals table.shop_table tr.x-sum__noterow > td {
  display: block;
  width: 100%;
  text-align: left;
}

.x-sum__note {
  display: block;
  margin: 0.5rem 0 0;
  font-size: 0.75rem;
  line-height: 1.45;
  color: var(--x-muted);
}

/*
 * ⚠️ THE CART'S FOOT IS TRIMMED, BECAUSE ITS CONTENT IS OFTEN SHORT.
 *
 * `.x-shop` carries the site's page rhythm — up to 4.5rem of bottom padding —
 * and `.x-footer` adds a 64px margin on top of that. On a long page those 136px
 * read as breathing room. On a cart holding one line they are a hole: measured at
 * 1440, the summary card ended at 488 and the footer did not begin until 624,
 * with nothing in between.
 *
 * Only the bottom is trimmed and only on the cart. The footer keeps its own
 * margin, so the sections are still clearly separated — the page just stops
 * reserving space for content that is not there.
 */
body.woocommerce-cart .x-container.x-shop {
  /*
   * ⚠️ THE TOP IS TRIMMED TOO, NOW THAT A LINK STARTS THE PAGE.
   *
   * `.x-shop` opens with up to 40px of page padding. That reads as a considered
   * margin under a heading; under a 21px text link it reads as the page failing
   * to start — measured 42px of empty cream between the header and "Continue
   * shopping". The cart has no `<h1>`, so nothing was earning that space.
   */
  padding-top: clamp(0.75rem, 2vw, 1.25rem);
  padding-bottom: clamp(0.75rem, 2vw, 1.25rem);
}

/* mobile.css re-asserts a top margin on this link; above the items it does not
   need one, the page padding is already the space. */
body.woocommerce-cart .x-cart__continue { margin-top: 0; }


/*
 * ⚠️ THE RESPONSIVE-TABLE RULE DRAWS A LINE UNDER EVERY ROW ON A PHONE.
 *
 * `@media (max-width: 767px) { .woocommerce table.shop_table tr }` gives each row
 * a bottom border and 0.75rem of padding — the treatment that turns a wide table
 * into stacked cards. It was harmless while these two summaries were rendered as
 * `<div>`s by theme templates. Handing those templates back brought real
 * `shop_table` markup to both, and the rule started drawing a rule under the
 * subtotal, the discount, the total and the coupon row.
 *
 * Only the border and that padding are undone; the design's own row padding is
 * set by more specific selectors and still wins.
 */
@media (max-width: 767px) {
  .woocommerce .cart_totals table.shop_table tr {
    border-bottom: 0;
    padding: 0;
  }
}


/*
 * ⚠️ THE RESPONSIVE TABLE PRINTS EACH CELL'S `data-title` BEFORE IT ON A PHONE.
 *
 * `@media (max-width: 767px) { .woocommerce table.shop_table td::before {
 * content: attr(data-title) } }` is how a wide table is made readable when its
 * header row is hidden. These summaries do not hide a header row — they have a
 * label in the `<th>` of every line — so the pseudo-element repeated it: a bold
 * "Shipping charges" from the `<th>`, then a grey "Shipping charges" from
 * `data-title`, one above the other.
 *
 * Another rule that was dead until these templates were handed back and real
 * `shop_table` markup appeared.
 */
@media (max-width: 767px) {
  .woocommerce .cart_totals table.shop_table td::before { content: none; }
}

/* Razorpay wraps its instruction line in a <p> that we blank in
   xl-store-copy.php; the empty element still took its margins. */
.x-pay__card p:empty { display: none; }

/* ⚠️ `.is-strong` AND `.is-saving` WERE IN THE MARKUP WITH NO RULES BEHIND THEM.
   The Partial COD card has always put `.is-strong` on its "Pay now" row — the
   amount actually being charged — and nothing styled it, so the row the whole
   page exists for looked like every other row. `.is-saving` is the same green
   the cart and drawer already use for money coming off. */
.x-pay__row.is-strong { font-size: 1.0625rem; }
.x-pay__row.is-strong > span:first-child { color: var(--x-ink); }
.x-pay__row.is-strong > span:last-child { font-weight: 700; }
.x-pay__row.is-saving > span,
.x-pay__row.is-saving .amount { color: var(--x-success); font-weight: 500; }

/* ────────────────────────────────────────────────────────────────────────────
 * Order tracking — WooCommerce's form and result, restyled
 * ──────────────────────────────────────────────────────────────────────────── */

/*
 * ⚠️ NOT ONE LINE OF THIS PAGE'S MARKUP IS OURS ANY MORE.
 *
 * It used to be `template-track-order.php`, a custom page template WooCommerce
 * never saw. The page now runs `[woocommerce_order_tracking]`, so the form is
 * `order/form-tracking.php` and the result is `order/tracking.php`, both from
 * the plugin. Everything below dresses that markup; the panel head, the rail
 * and the item list are added through the templates' own hooks in
 * mu-plugins/xl-track-woo.php.
 */
/* ⚠️ ALIGNED LEFT, NOT CENTRED.
   `.x-prose` is a 720px reading column that starts at the page's left margin,
   so `margin: 0 auto` centred these cards *inside it* — 88px to the right of
   the "Track order" heading above them, matching nothing on the page. They
   share the heading's left edge instead. */
.page .track_order,
.x-page .track_order {
  max-width: 34rem;
  margin-inline: 0;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.25rem, 4vw, 2rem);
}

.x-trackw__head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.x-trackw__icon {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: var(--x-r-pill);
  background: var(--x-bg-alt);
  color: var(--x-ink);
}

.x-trackw__headtitle {
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.2;
  margin: 0;
}

.x-trackw__headsub { margin: 0; font-size: 0.8125rem; color: var(--x-muted); }

/* ⚠️ `form-row-first` / `form-row-last` are WooCommerce's own float classes.
   They put the two fields side by side, which at 320px leaves an order number
   box about eight characters wide. Grid instead, and let it stack. */
.track_order .form-row {
  float: none;
  width: auto;
  margin: 0 0 0.875rem;
  padding: 0;
}

.track_order label {
  display: block;
  margin-bottom: 0.375rem;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--x-muted);
}

.track_order .input-text {
  display: block;
  width: 100%;
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--x-line-strong, var(--x-line));
  border-radius: var(--x-r-md);
  background: var(--x-white);
  color: var(--x-ink);
  font-family: var(--font-body);
  font-size: 1rem;
}

.track_order .input-text:focus-visible {
  outline: 2px solid var(--x-ink);
  outline-offset: 1px;
}

.track_order button[type="submit"] {
  display: block;
  width: 100%;
  margin-top: 0.25rem;
  padding: 0.9375rem 1.25rem;
  border: 0;
  border-radius: var(--x-r-pill);
  background: var(--x-dark);
  color: var(--x-bg);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  cursor: pointer;
}

.track_order button[type="submit"]:hover { opacity: 0.9; }

.track_order .clear { display: none; }

.x-trackw__throttle {
  margin: 0 0 1rem;
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--x-line-strong, var(--x-line));
  border-left: 3px solid var(--x-danger, #A2503C);
  border-radius: var(--x-r-sm);
  background: var(--x-bg-alt);
  font-size: 0.875rem;
}

.x-trackw__alt {
  margin: 1rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--x-line);
  font-size: 0.8125rem;
  color: var(--x-muted);
}

.x-trackw__alt a { color: var(--x-ink); text-underline-offset: 3px; }

/* ── The result ─────────────────────────────────────────────────────────── */

/* WooCommerce prints the status inside `p.order-info`; the filter in
   xl-track-woo.php replaces its sentence with these three spans. */
.order-info {
  max-width: 34rem;
  margin: 0 0 1rem;
  padding: clamp(1.25rem, 4vw, 1.75rem);
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  display: grid;
  gap: 0.25rem;
}

.x-trackw__eyebrow {
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--x-muted);
}

.x-trackw__state {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 5vw, 2rem);
  line-height: 1.15;
}

.x-trackw__ref { font-size: 0.8125rem; color: var(--x-muted); }

.x-trackw__result {
  max-width: 34rem;
  margin-inline: 0;
  background: var(--x-white);
  border: 1px solid var(--x-line);
  border-radius: var(--x-r-lg);
  padding: clamp(1.25rem, 4vw, 1.75rem);
}

/* ⚠️ The rail is a list, and the connecting line is drawn on the items rather
   than as one element behind them — a single bar cannot stop at the last dot
   when the number of stages changes with the courier's report. */
.x-trackw__rail {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  display: grid;
  gap: 0;
}

.x-trackw__step {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0;
  font-size: 0.9375rem;
  color: var(--x-muted);
}

.x-trackw__step:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 0.3125rem;
  top: 1.75rem;
  bottom: -0.25rem;
  width: 1px;
  background: var(--x-line);
}

.x-trackw__dot {
  width: 0.6875rem;
  height: 0.6875rem;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--x-line-strong, var(--x-line));
  background: var(--x-white);
}

.x-trackw__step.is-done { color: var(--x-ink); }
.x-trackw__step.is-done .x-trackw__dot { background: var(--x-success); border-color: var(--x-success); }
.x-trackw__step.is-current { font-weight: 600; }
.x-trackw__step.is-current .x-trackw__dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--x-success) 22%, transparent); }

.x-trackw__exception {
  margin: 0 0 1.25rem;
  padding: 0.875rem 1rem;
  border-radius: var(--x-r-sm);
  background: color-mix(in srgb, var(--x-danger, #A2503C) 10%, var(--x-white));
  color: var(--x-ink);
  font-size: 0.9375rem;
}

.x-trackw__facts {
  margin: 0 0 1.25rem;
  padding: 0.875rem 0 0;
  border-top: 1px solid var(--x-line);
  display: grid;
  gap: 0.5rem;
}

.x-trackw__fact { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.875rem; }
.x-trackw__fact dt { color: var(--x-muted); }
.x-trackw__fact dd { margin: 0; font-weight: 500; text-align: right; }

.x-trackw__items {
  list-style: none;
  margin: 0;
  padding: 0.875rem 0 0;
  border-top: 1px solid var(--x-line);
  display: grid;
  gap: 0.625rem;
}

.x-trackw__item { display: flex; align-items: center; gap: 0.75rem; font-size: 0.875rem; }
.x-trackw__itemimg { width: 3rem; height: 3rem; object-fit: cover; border-radius: var(--x-r-sm); flex: none; }
.x-trackw__itemname { flex: 1 1 auto; min-width: 0; }
.x-trackw__itemqty { color: var(--x-muted); font-variant-numeric: tabular-nums; }

.x-trackw__again { margin: 1.25rem 0 0; font-size: 0.8125rem; }
.x-trackw__again a { color: var(--x-muted); text-underline-offset: 3px; }

/* WooCommerce's customer order notes list, when there are any. */
.woocommerce-page .commentlist.notes { max-width: 34rem; margin: 1rem 0 0; padding: 0; list-style: none; }

/*
 * ⚠️ THE RECEIPT BRANCH OF `/checkout/order-pay/`, NOW THAT IT HAS NO TEMPLATE.
 *
 * `woocommerce/checkout/order-receipt.php` is deleted. The heading, the warning
 * and the price breakdown come from `before_woocommerce_pay`, the safety note
 * from `after_woocommerce_pay`, and everything between them —
 * `ul.order_details` and the gateway's button — is WooCommerce's own markup,
 * restyled here.
 *
 * ⚠️ `:has(ul.order_details)` IS THE DISCRIMINATOR.
 *
 * The same URL serves `form-pay.php` when no method has been chosen, which is
 * carded by the `:has(form#order_review)` rules above. The list is what the
 * receipt branch has and the form branch does not.
 */
/* The card itself is `.x-pay__card`, printed by the hooks — so the rules above
   for the Partial COD card, the gateway button and its states all still apply,
   and the container rule that already stands down for `.x-pay` handles the
   measure. Only the list below needs anything new. */

/* The breakdown above and WooCommerce's list below have to read as one block,
   so the rows' shared top border is dropped where the list continues it. */
body.woocommerce-order-pay .x-pay__rows { margin-bottom: 0; }

/*
 * ⚠️ `order` PUTS "TOTAL:" FIRST, AND THAT IS THE WHOLE TRICK.
 *
 * WooCommerce prints the list as Order number, Date, Total, Payment method —
 * fine for a receipt, wrong here, where the rows above end at Shipping and the
 * reader is waiting for the total. Flex ordering lifts it to the top of the
 * list so the money still reads top to bottom, and the two reference lines fall
 * below it. No markup was moved to do this.
 */
body.woocommerce-order-pay ul.order_details {
  display: flex;
  flex-direction: column;
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
}

body.woocommerce-order-pay ul.order_details li.total { order: -1; }

body.woocommerce-order-pay ul.order_details li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6875rem 0;
  border-bottom: 1px solid var(--x-line);
  font-size: 0.9375rem;
  color: var(--x-muted);
}

body.woocommerce-order-pay ul.order_details li strong {
  font-weight: 600;
  color: var(--x-ink);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* The total is the loudest thing on a page whose job is to collect it. */
body.woocommerce-order-pay ul.order_details li.total { font-size: 1.0625rem; color: var(--x-ink); }
body.woocommerce-order-pay ul.order_details li.total strong { font-weight: 700; }

/* Order number and date are references, not amounts. */
body.woocommerce-order-pay ul.order_details li.order,
body.woocommerce-order-pay ul.order_details li.date { font-size: 0.8125rem; }
body.woocommerce-order-pay ul.order_details li.order strong,
body.woocommerce-order-pay ul.order_details li.date strong { font-weight: 400; color: var(--x-ink-soft); }

body.woocommerce-order-pay ul.order_details li:last-child { border-bottom: 0; }
body.woocommerce-order-pay .woocommerce .clear { display: none; }

/*
 * ⚠️ THE BREADCRUMB ON A PLAIN PAGE, MATCHED TO THE ABOUT PAGE'S RHYTHM.
 *
 * The tracking page is an ordinary WordPress page now, so it takes `.x-page`'s
 * 48px top padding and the theme's 1.6 line-height — against the About page's
 * hero, which starts at 32px and sets the trail on a normal line box. Side by
 * side the two trails sat 16px apart vertically, the tracking one was 33px tall
 * against About's 18px, and it left 16px to its heading where About leaves 42px.
 *
 * ⚠️ `:has(> .x-crumbs)` RATHER THAN A PAGE ID.
 *
 * `.x-page` is every plain page on the site; only the ones that actually render
 * a trail should change their top padding. Keying on the trail's presence means
 * this stays correct when another page is added to
 * `xl_seo_shows_breadcrumbs()` — and does nothing to the pages that are not.
 */
/* The About hero's own value, copied rather than approximated — it is what puts
   the trail 18px below the header on a phone and 32px on a desktop. */
.x-container.x-page:has(> .x-crumbs) { padding-top: clamp(18px, 3vw, 32px); }

/*
 * ⚠️ `.x-crumbs`'s OWN 14px TOP PADDING IS REMOVED HERE, NOT REDUCED ELSEWHERE.
 *
 * brand.css gives every trail `padding-block: 14px 0` so it is not flush against
 * the header on the shop and product pages, which have no container padding of
 * their own. This page does have it, so the two stacked and the trail sat 14px
 * lower than About's. The padding is right where it is; it is only wrong here.
 */
.x-page > .x-crumbs { padding-top: 0; margin-bottom: 2.8125rem; }

/* About sets the trail on a `normal` line box; inheriting the page's 1.6 made
   this one nearly twice as tall for the same 12px text. */
.x-page > .x-crumbs .x-crumbs__list { line-height: normal; }
