/*
Theme Name: Xyvira Luxe
Theme URI: https://xyviraluxe.com
Author: Xyvira Luxe
Description: Storefront theme for Xyvira Luxe — ports the Veluno design system from the Next.js storefront so WooCommerce serves every page.
Version: 1.0.0
Requires at least: 6.4
Requires PHP: 8.1
License: GPL-2.0-or-later
Text Domain: xyvira
*/

/* ────────────────────────────────────────────────────────────────────────────
 * Design tokens — copied verbatim from the storefront's globals.css so the two
 * cannot drift while both exist. Every colour below is already in use on the
 * live storefront; nothing here was invented for WordPress.
 * ──────────────────────────────────────────────────────────────────────────── */

:root {
  --x-bg: #f4f1ea;            /* cream page background */
  --x-bg-alt: #ede8df;        /* beige alternating band */
  --x-surface: #e8e2d7;       /* greige card fill */
  --x-surface-warm: #efe7dd;  /* warm promo band */
  --x-dark: #1e1d1b;          /* buttons / dark sections */
  --x-ink: #201f1c;           /* primary text */
  --x-ink-soft: #6f6a5e;      /* long-form body */
  --x-muted: #8c8579;         /* secondary text */
  --x-line: #e1dace;          /* hairline borders */
  --x-line-strong: #d8d0c2;
  --x-line-header: #e7e1d5;
  --x-accent: #c9694a;        /* coral — sparing */
  --x-accent-hover: #b05a3e;
  --x-white: #ffffff;
  --x-field: #faf8f3;
  --x-success: #4a7c59;
  --x-danger: #a94436;

  /* The Fallback faces are metric-matched re-cuts declared in fonts.css. They
     must sit immediately after the real font, before any system face, or the
     browser reaches a mismatched fallback first and the swap becomes visible. */
  --font-display: "Cormorant Garamond", "Cormorant Fallback", Georgia, serif;
  --font-body: "Outfit", "Outfit Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* 75rem — matches the storefront container exactly. Not 1280, not 1680. */
  /*
   * ⚠️ THREE RADII, NOT EIGHT.
   *
   * A census of the rendered checkout found eight different corner radii on one
   * page — 8, 10, 12, 14, 16, 20, 999 and 9999px. No single one was wrong; the
   * spread was, because corners are the most repeated shape on a page and
   * inconsistency there reads as "assembled" rather than "designed".
   *
   * They tighten on mobile. A 20px corner on a full-width card at 390px looks
   * soft and bulky; the same card at 14px reads crisp. Desktop keeps the
   * generous feel because the cards are smaller relative to the viewport.
   */
  --x-r-sm: 0.625rem;   /* 10px — inputs, chips, small controls */
  --x-r-md: 0.875rem;   /* 14px — inner panels */
  --x-r-lg: 1.25rem;    /* 20px — cards and sections */
  --x-r-pill: 999px;    /* buttons only */

  --x-container: 75rem;
  --x-pad: 1.25rem;   /* 20px  */
  --x-pad-lg: 2rem;   /* 32px  */
}

/* ── Reset ─────────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

/*
 * ⚠️ STICKY FOOTER. A short page — an empty cart, a 404, a thin policy page —
 * left the footer floating in the middle of a tall screen with cream below it,
 * which reads as the page having failed to finish loading.
 */
html { min-height: 100%; }

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  margin: 0;
  background: var(--x-bg);
  color: var(--x-ink);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* ⚠️ `width: 100%` IS LOAD-BEARING. An `auto` margin on the cross axis of a
   flex item cancels `align-items: stretch` — the item sizes to its content and
   centres instead. xl-checkout-theme.php sets `margin: 0 auto` on main, so the
   moment body became a flex column, main collapsed from 1920px to 701px and
   took the whole layout with it. */
#x-main { flex: 1 0 auto; width: 100%; min-width: 0; }
.x-footer { flex-shrink: 0; }

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--x-ink);
  margin: 0;
  text-wrap: balance;
}

/*
 * ⚠️ iOS SAFARI AUTO-ZOOMS ON ANY FOCUSED CONTROL UNDER 16px.
 * The design uses 14px inputs; without this, tapping a checkout field zooms the
 * viewport on every iPhone. Never "fix" that with maximum-scale=1 — that
 * disables pinch zoom, which is an accessibility failure.
 */
@media (max-width: 639px) {
  input:not([type="checkbox"]):not([type="radio"]),
  select, textarea { font-size: 16px !important; }
}

/* ── Layout ────────────────────────────────────────────────────────────────── */

.x-container {
  width: 100%;
  max-width: var(--x-container);
  margin-inline: auto;
  padding-inline: var(--x-pad);
}

@media (min-width: 1024px) {
  .x-container { padding-inline: var(--x-pad-lg); }
}

/* ── Header ────────────────────────────────────────────────────────────────── */

.x-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--x-bg) 95%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--x-line-header);
}

/*
 * Promotional bar.
 *
 * ⚠️ IT IS THE FIRST THING ON EVERY PAGE, SO IT HAS TO EARN THE SPACE.
 * Flat small text across a beige band reads as boilerplate and gets ignored.
 * The message stays quiet; the coupon code is the one element given weight,
 * because it is the only part anyone needs to act on.
 */
.x-promo {
  background: var(--x-dark);
  border-bottom: 1px solid var(--x-dark);
  color: var(--x-bg);
  font-size: 0.75rem;
  overflow: hidden;
}

.x-promo__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.5rem 0.75rem;
  min-height: 2.25rem;
  padding-block: 0.375rem;
  text-align: center;
}

@media (min-width: 1024px) { .x-promo__inner { min-height: 2.5rem; } }

.x-promo__msg {
  letter-spacing: 0.02em;
  color: rgba(244, 241, 234, 0.88);
}

a.x-promo__msg { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: rgba(244, 241, 234, 0.35); }
a.x-promo__msg:hover { color: var(--x-bg); text-decoration-color: var(--x-bg); }

/* The code chip: monospaced digits, a dashed edge, and a copy affordance that
   only appears when it can actually do something. */
.x-promo__code {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* Measured at 29px tall. It copies a coupon code — a miss means the customer
     types it by hand or gives up on the discount entirely. */
  min-height: 2.25rem;
  padding: 0.35rem 0.7rem;
  touch-action: manipulation;
  border: 1px dashed rgba(244, 241, 234, 0.42);
  border-radius: var(--x-r-sm);
  background: rgba(244, 241, 234, 0.08);
  color: var(--x-bg);
  font: inherit;
  font-weight: 600;
  letter-spacing: 0.14em;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.x-promo__code:hover { background: rgba(244, 241, 234, 0.16); border-color: rgba(244, 241, 234, 0.7); }
.x-promo__code:focus-visible { outline: 2px solid var(--x-bg); outline-offset: 2px; }

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

.x-promo__codehint {
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(244, 241, 234, 0.6);
  /* Hidden until the script confirms copying will work — an affordance that
     does nothing is worse than none. */
  display: none;
}

.x-promo__code.is-copyable .x-promo__codehint { display: inline; }
.x-promo__code.is-copied { background: var(--x-accent); border-color: var(--x-accent); border-style: solid; }
.x-promo__code.is-copied .x-promo__codehint { color: rgba(255, 255, 255, 0.85); }

/* Narrow phones: the hint is the first thing to go, then the chip wraps. */
@media (max-width: 26rem) {
  .x-promo__codehint { display: none !important; }
  .x-promo__inner { gap: 0.375rem 0.5rem; }
  .x-promo { font-size: 0.6875rem; }
}

.x-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 4rem;
}

.x-header__left { display: flex; align-items: center; gap: 0.375rem; }

@media (min-width: 1024px) { .x-header__left { gap: 0.75rem; } }

.x-logo { display: flex; align-items: center; gap: 0.625rem; flex-shrink: 0; }
.x-logo__mark { height: 1.75rem; width: auto; }
.x-logo__rule { display: none; width: 1px; height: 1.25rem; background: rgb(30 29 27 / 0.15); }
.x-logo__word { display: none; height: 1rem; width: auto; }

@media (min-width: 1024px) {
  .x-logo { gap: 0.75rem; }
  .x-logo__mark { height: 2rem; }
  .x-logo__rule { display: block; height: 1.5rem; }
  .x-logo__word { display: block; height: 1.25rem; }
}

.x-nav { display: none; align-items: center; gap: 2rem; }
@media (min-width: 1024px) { .x-nav { display: flex; } }

/* wp_nav_menu returns a list; the fallback returns bare anchors. Both have to
   lay out identically. */
.x-nav__list {
  display: flex;
  align-items: center;
  gap: 2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.x-nav a {
  font-size: 0.875rem;
  color: #3a362e;
  transition: color 0.15s ease;
}
.x-nav a:hover { color: var(--x-dark); }

.x-mobile-menu .x-nav__list { display: block; list-style: none; margin: 0; padding: 0; }

.x-header__actions { display: flex; align-items: center; gap: 0.375rem; }

/* 44px tap targets — the minimum comfortable size on a phone. */
.x-icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 2.75rem;
  width: 2.75rem;
  border-radius: var(--x-r-pill);
  color: var(--x-ink);
  background: none;
  border: 0;
  cursor: pointer;
  transition: background-color 0.15s ease;
  position: relative;
}
.x-icon-btn:hover { background: var(--x-surface); }

.x-cart-count {
  position: absolute;
  top: 0.375rem;
  right: 0.25rem;
  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;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* Mobile menu — a checkbox toggle so navigation works without JavaScript. */
.x-burger { display: flex; }
@media (min-width: 1024px) { .x-burger { display: none; } }

#x-menu-toggle { display: none; }

.x-mobile-menu {
  display: none;
  border-top: 1px solid var(--x-line-header);
  background: var(--x-bg);
  padding: 0.75rem var(--x-pad) 1.25rem;
}
#x-menu-toggle:checked ~ .x-mobile-menu { display: block; }
@media (min-width: 1024px) { .x-mobile-menu { display: none !important; } }

.x-mobile-menu a {
  display: block;
  padding: 0.75rem 0;
  font-size: 0.9375rem;
  color: #3a362e;
  border-bottom: 1px solid var(--x-line);
}
.x-mobile-menu a:last-child { border-bottom: 0; }

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

.x-footer {
  border-top: 1px solid var(--x-line);
  background: var(--x-bg-alt);
  margin-top: 4rem;
}

.x-footer__inner { padding-block: 2.25rem; }
@media (min-width: 1024px) { .x-footer__inner { padding-block: 3.5rem; } }

.x-footer__top {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
}
@media (min-width: 1280px) {
  .x-footer__top { grid-template-columns: 1.1fr 1.4fr; }
}

.x-footer__brand { display: flex; flex-direction: column; gap: 1.5rem; }
.x-footer__brand img { height: 1.75rem; width: auto; align-self: flex-start; }
.x-footer__brand p {
  max-width: 24rem;
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--x-ink-soft);
}

.x-footer__cols {
  display: grid;
  /*
   * ⚠️ THREE ACROSS ON A PHONE, NOT TWO — THERE ARE THREE COLUMNS.
   *
   * Two columns left the third (Help) orphaned on a row of its own, and since
   * row height is set by the tallest cell, the short Shop and Brand columns
   * opened a ~120px hole above it. Three across removes the second row
   * entirely. Measured at 390px: 108px per column against a longest label
   * ("Track Order") of ~78px, so nothing wraps.
   *
   * A fourth column would break this. If one is ever added, drop back to two
   * here and let the 512px breakpoint take over sooner.
   */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
}
@media (min-width: 512px) {
  .x-footer__cols { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2rem; }
}

.x-footer__cols h2 { font-family: var(--font-body); font-size: 0.8125rem; font-weight: 600; }
.x-footer__cols ul { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: 0.625rem; }
.x-footer__cols a { font-size: 0.8125rem; color: var(--x-muted); transition: color 0.15s ease; }
.x-footer__cols a:hover { color: var(--x-dark); }

.x-footer__bottom {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid #ded6c8;
  display: flex;
  flex-direction: column;
  /*
   * ⚠️ LEFT, NOT CENTRED — THE COLUMN IS STACKED HERE.
   *
   * `center` centred every child individually. The copyright and legal links
   * are long enough to fill the width so they still LOOKED left-aligned, but
   * the social row is only ~84px wide, so it alone sat marooned in the middle
   * of the footer at x153 while everything else began at x16. One stray
   * alignment, and it read as the icons being wrong.
   *
   * The row direction below re-centres deliberately: there it aligns items
   * against each other vertically, which is a different question.
   */
  align-items: flex-start;
  gap: 1rem;
}
@media (min-width: 1024px) {
  .x-footer__bottom {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
}
.x-footer__bottom p { margin: 0; font-size: 0.75rem; color: var(--x-muted); }

.x-social { display: flex; align-items: center; gap: 0.75rem; }
.x-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 2.25rem;
  width: 2.25rem;
  border-radius: var(--x-r-pill);
  background: #e0d9cc;
  color: var(--x-dark);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.x-social a:hover { background: var(--x-dark); color: var(--x-bg); }

/* ── Buttons ───────────────────────────────────────────────────────────────── */

.x-btn,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
.wp-block-button__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  /*
   * ⚠️ 44px FLOOR ON EVERY BUTTON, SET ONCE.
   *
   * An audit at phone width found buttons at 39–43px scattered across the
   * homepage — each a near miss, each fixed separately in the past and each
   * drifting back. Setting the floor on the shared button rule means a new
   * button is the right size by default instead of by remembering.
   *
   * `min-height` only, so buttons with more padding keep it.
   */
  min-height: 2.75rem;
  touch-action: manipulation;
  background: var(--x-dark);
  color: var(--x-bg);
  border: 0;
  border-radius: var(--x-r-pill);
  padding: 0.875rem 2rem;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.x-btn:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce #respond input#submit:hover {
  background: var(--x-dark);
  color: var(--x-bg);
  transform: translateY(-2px);
  opacity: 0.92;
}

.woocommerce button.button:disabled,
.woocommerce button.button.disabled {
  opacity: 0.5;
  transform: none;
  cursor: not-allowed;
}

.x-btn--ghost {
  background: transparent;
  color: var(--x-ink);
  border: 1px solid var(--x-line-strong);
}
.x-btn--ghost:hover { background: var(--x-surface); }

@media (prefers-reduced-motion: reduce) {
  .x-btn, .woocommerce a.button, .woocommerce button.button { transition: none; }
  .x-btn:hover, .woocommerce a.button:hover { transform: none; }
}


/* ⚠️ FOOTER LINKS MEASURED 16px TALL.
   Line-height alone on a list of links puts four targets inside a thumb's
   width of each other. The padding is invisible and makes each one its own
   target — on a store where nearly all traffic is mobile, the footer is real
   navigation, not decoration. */
.x-footer__cols li a {
  display: inline-block;
  padding-block: 0.45rem;
  touch-action: manipulation;
}

/* ── Footer legal links ───────────────────────────────────────────────────── */
/* Privacy / Terms / Refunds / Shipping, required on every page. Quiet by
   design — present and findable, not competing with the navigation above. */
.x-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.25rem;
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
}
.x-footer__legal a {
  font-size: 0.75rem;
  color: var(--x-muted, #8c8579);
  text-decoration: none;
}
.x-footer__legal a:hover { color: var(--x-ink, #201f1c); text-decoration: underline; text-underline-offset: 3px; }

/* ══ Homepage hero — full-bleed banner ════════════════════════════════════ */
/* Mobile-first. The desktop rules only widen and shorten it. */

.x-hero2 { position: relative; }

/* ⚠️ THE TRACK RESERVES ITS HEIGHT SO SLIDES CANNOT SHIFT THE PAGE.
   Slides are stacked in one grid cell rather than laid side by side. */
.x-hero2__track { display: grid; }

/*
 * ⚠️ THE SLIDE IS A GRID SO THE TEXT CAN MAKE IT TALLER.
 *
 * The overlay used to be `position: absolute; inset: 0`, sized by the image
 * alone. At 320px the headline wraps to three lines, the text becomes taller
 * than a 4:3 image, and an absolutely positioned block cannot push its parent —
 * so the copy and the CTA spilled out of the hero and landed on top of the
 * section below it.
 *
 * Stacking the link and the overlay in one grid cell makes the cell as tall as
 * whichever is taller. The image still fills it via `height: 100%`, and on
 * wider screens where the image wins nothing changes at all.
 */
.x-hero2__slide {
  grid-area: 1 / 1;
  position: relative;
  display: grid;
  grid-template-areas: "stack";
}
.x-hero2__link,
.x-hero2__overlay,
.x-hero2__slide::after { grid-area: stack; }

/*
 * ⚠️ `display` MUST BE RESTORED, OR THE STACK DOES NOT STACK.
 *
 * The `hidden` attribute carries `display: none`, so hidden slides left the
 * grid and the track sized itself to whichever slide showed — every change
 * resized the banner and shoved the page. `visibility: hidden` hides it
 * visually AND from assistive tech while keeping its cell.
 */
.x-hero2__slide[hidden] { display: block; visibility: hidden; }

.x-hero2__link { display: block; min-height: 100%; }

/* Portrait on a phone, a wide band on desktop. `cover` crops rather than
   squashes, and the fixed ratio means no reflow when the image lands. */
.x-hero2__slide img {
  width: 100%;
  /* Fills the cell however tall the text makes it; `cover` crops rather than
     stretches, and the aspect-ratio below still sets the minimum. */
  height: 100%;
  /*
   * ⚠️ 4:5 TOOK 625px — ALMOST THE WHOLE FIRST SCREEN.
   *
   * A banner that fills the phone entirely means the visitor's first scroll
   * reveals more banner. 4:3 still reads as a proper banner and gives back
   * ~160px, which is most of a product card.
   */
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}

/* ── Text over the image ──────────────────────────────────────────────────── */
.x-hero2__overlay {
  /* In flow within the grid cell, not absolute — see the note on .x-hero2__slide. */
  position: relative;
  display: grid;
  align-items: end;
  pointer-events: none;
  /*
   * ⚠️ THE TEXT MUST OUTRANK ITS OWN SCRIM.
   *
   * The scrim is `.x-hero2__slide::after`, and a generated ::after is the last
   * child — so it painted OVER the headline instead of under it. The result
   * looked exactly like a scrim that was too weak (washed-out text), which sent
   * me strengthening the gradient twice; every increase made the text worse,
   * because the veil was on the wrong side of it.
   *
   * z-index 1 puts the words above the scrim and below the controls (z-index 2).
   */
  z-index: 1;
}
/* Only the text block takes clicks back, so the whole banner stays a link. */
.x-hero2__text { pointer-events: auto; padding: 1.5rem 0 2rem; max-width: 32rem; }

.x-hero2__slide.is-align-centre .x-hero2__overlay,
.x-hero2__slide.is-align-center .x-hero2__overlay { justify-items: center; text-align: center; }
.x-hero2__slide.is-align-right .x-hero2__overlay { justify-items: end; text-align: right; }

/*
 * ⚠️ A SCRIM, BECAUSE TEXT ON A PHOTOGRAPH HAS NO GUARANTEED CONTRAST.
 *
 * The headline sits over an image nobody has checked for contrast, and a pale
 * sky behind white type is unreadable — worse, it passes on the designer's
 * screen and fails on a phone in daylight. A gradient from the bottom keeps the
 * type on a dark enough ground whatever the photograph does.
 */
.x-hero2__slide::after {
  content: "";
  /* ⚠️ MEASURED AGAINST THE WORST CASE, NOT THE SAMPLE IMAGE.
     The first version topped out at 0.45 alpha where the headline sits, which
     was fine over a dark photo and unreadable over the pale beige one actually
     in use. These stops assume a near-white image underneath. */
  background: linear-gradient(to top,
    rgba(20, 18, 16, 0.88) 0%,
    rgba(20, 18, 16, 0.70) 38%,
    rgba(20, 18, 16, 0.15) 78%,
    rgba(20, 18, 16, 0) 100%);
  pointer-events: none;
}
/* Artwork with the words already in it needs no scrim over the top of them. */
.x-hero2__slide.is-align-none::after { display: none; }

.x-hero2__eyebrow {
  margin: 0 0 0.6rem;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #f6ded3;
  text-shadow: 0 1px 10px rgba(20, 18, 16, 0.5);
}
.x-hero2__title {
  font-family: var(--x-font-display, Georgia, serif);
  font-size: clamp(1.85rem, 7.5vw, 3.5rem);
  line-height: 1.06;
  letter-spacing: -0.015em;
  margin: 0 0 0.6rem;
  color: #fff;
  text-wrap: balance;
  /* A gradient handles the average; a blown-out highlight directly behind a
     letter still eats it. This costs nothing and rescues that case. */
  text-shadow: 0 1px 14px rgba(20, 18, 16, 0.45);
}
.x-hero2__lead {
  margin: 0 0 1.25rem;
  font-size: 0.95rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.94);
  max-width: 34ch;
  text-shadow: 0 1px 10px rgba(20, 18, 16, 0.45);
}
.x-hero2__cta {
  min-height: 2.875rem;
  display: inline-flex;
  align-items: center;
  background: #fff;
  color: var(--x-dark, #1e1d1b);
}
.x-hero2__cta:hover { background: var(--x-bg, #f4f1ea); }

/* ── Controls ─────────────────────────────────────────────────────────────── */
.x-hero2__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border-radius: var(--x-r-pill);
  border: 0;
  background: rgba(255, 255, 255, 0.85);
  color: var(--x-dark, #1e1d1b);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.x-hero2__arrow.is-prev { left: 0.75rem; }
.x-hero2__arrow.is-next { right: 0.75rem; }
.x-hero2__arrow:hover { background: #fff; }

.x-hero2__rail {
  position: absolute;
  left: 0; right: 0; bottom: 0.5rem;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
}
.x-hero2__dots { display: flex; align-items: center; gap: 0.25rem; }
.x-hero2__dot,
.x-hero2__pause {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.x-hero2__dot { width: 1.75rem; height: 2.5rem; display: grid; place-items: center; }
.x-hero2__dot span {
  display: block;
  width: 1.25rem; height: 0.3rem;
  border-radius: var(--x-r-pill);
  background: rgba(255, 255, 255, 0.5);
  /* transform, not width — width relayouts the whole dot row every frame. */
  transform: scaleX(0.4);
  transform-origin: center;
  transition: background 150ms ease, transform 150ms ease;
}
.x-hero2__dot.is-current span { transform: scaleX(1); background: #fff; }

.x-hero2__pause {
  width: 2.5rem; height: 2.5rem;
  display: grid; place-items: center;
  color: #fff;
}
.x-hero2__pauseicon {
  width: 0.6rem; height: 0.6rem;
  border-left: 3px solid currentColor;
  border-right: 3px solid currentColor;
}
.x-hero2.is-paused .x-hero2__pauseicon {
  border: 0;
  width: 0; height: 0;
  border-left: 0.6rem solid currentColor;
  border-top: 0.38rem solid transparent;
  border-bottom: 0.38rem solid transparent;
  margin-left: 0.15rem;
}

.x-hero2:focus-visible,
.x-hero2__arrow:focus-visible,
.x-hero2__pause:focus-visible,
.x-hero2__dot:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

@media (min-width: 48rem) {
  /*
   * ⚠️ SHORT AND WIDE, LIKE THE COMPETITION.
   *
   * Minimalist and Dot & Key both run roughly 4:1 at ~330px tall on a 1280
   * screen, so bestsellers start almost immediately. A tall hero looks
   * impressive and pushes everything buyable below the fold.
   */
  .x-hero2__slide img { aspect-ratio: 16 / 5; max-height: 30rem; }
  .x-hero2__text { padding: 0; max-width: 34rem; }
  .x-hero2__overlay { align-items: center; }
  .x-hero2__title { font-size: clamp(2.25rem, 3.4vw, 3.25rem); }
  .x-hero2__lead { font-size: 1rem; }

  /* With the text vertically centred, a bottom-up gradient would leave the
     headline on bare photograph. Side scrim instead. */
  .x-hero2__slide::after {
    background: linear-gradient(to right,
      rgba(20, 18, 16, 0.88) 0%, rgba(20, 18, 16, 0.72) 34%,
      rgba(20, 18, 16, 0.25) 62%, rgba(20, 18, 16, 0) 82%);
  }
  .x-hero2__slide.is-align-right::after {
    background: linear-gradient(to left,
      rgba(20, 18, 16, 0.88) 0%, rgba(20, 18, 16, 0.72) 34%,
      rgba(20, 18, 16, 0.25) 62%, rgba(20, 18, 16, 0) 82%);
  }
  .x-hero2__slide.is-align-centre::after,
  .x-hero2__slide.is-align-center::after {
    background: rgba(20, 18, 16, 0.5);
  }

  .x-hero2__arrow.is-prev { left: 1.5rem; }
  .x-hero2__arrow.is-next { right: 1.5rem; }
  .x-hero2__rail { bottom: 1rem; }
}

@media (prefers-reduced-motion: reduce) {
  .x-hero2__dot span { transition: none; }
}

/* ── The brand sentence below the hero ──────────────────────────────────────
   One line of real text on a page whose headline lives inside a JPEG. Quiet on
   purpose: it is there to be read once and to be crawlable, not to compete
   with the banner above it or the products below. */
.x-intro { padding-block: 1.25rem 0; }

.x-intro__text {
  margin: 0 auto;
  max-width: 46rem;
  text-align: center;
  color: var(--x-muted);
  font-size: .95rem;
  line-height: 1.6;
  text-wrap: balance;
}

.x-intro__text strong { color: var(--x-ink); font-weight: 600; }

@media (min-width: 1024px) {
  .x-intro { padding-block: 1.75rem 0; }
  .x-intro__text { font-size: 1rem; }
}
