/* ==========================================================================
   LuxScout — storefront
   ==========================================================================
   The retail surface: navigation, product grids, product pages, the bag and
   checkout. Every value comes from tokens.css — this file defines no palette.

   The brief for the look is "premium because of quality, not decoration":
   generous whitespace, a quiet type hierarchy, photography doing the selling.
   Gold appears as a hairline and an accent on text, never as a fill, a badge
   or a border around everything. There are no urgency banners, countdowns,
   "N people viewing" strips or invented discount flags — not because they were
   styled out, but because nothing in the data model can produce them.

   Mobile first throughout: TikTok traffic arrives on a phone, so the phone
   layout is the base and the desktop rules are the enhancement.
   ========================================================================== */

/* ---- base ---------------------------------------------------------------
   The storefront pages load tokens.css + this file and nothing else. The reset
   lived in styles.css — the stylesheet of the previous editorial site, which no
   storefront page loads — so every page here shipped with the user-agent's 8px
   body margin AND content-box sizing. `.lx-wrap` is `width:100%` plus
   `padding-inline: var(--gutter)`, so under content-box it computed to
   viewport + 2 × gutter: at 1440 the document was 1536px wide. That is the
   horizontal scrollbar on the live site, and the reason the header and footer
   backgrounds stop short of the right edge. It has to live here. */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body.lx-shop {
  margin: 0;
  background: var(--porcelain);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'kern' 1;
}

/* THE `hidden` ATTRIBUTE MUST WIN.
   `hidden` hides through a UA rule of near-zero specificity, so ANY author
   rule that sets `display` on the same element silently defeats it. The
   account page is what this cost: measured live, [data-account-resolving]
   and [data-account] both carried hidden=true and both still computed to
   `display: grid` — 274px of loading skeletons and a 1,328px account panel
   rendered on top of the signed-out state. The page had finished loading
   with no pending requests and no console error; it simply looked like it
   never stopped loading.

   Seven components had already been patched one at a time
   (.lx-nav-panel[hidden], .lx-drawer[hidden], .lx-refine[hidden] and so on),
   which is the same bug found seven times and fixed seven times. One rule
   ends the class of defect: if the attribute is present, the element is
   gone, whatever any other rule says.

   `!important` is deliberate and is the standard remedy — `hidden` is a
   statement of fact about the document, not a style suggestion. */
[hidden] { display: none !important; }

/* The header is injected by shop-chrome.js into an empty <div data-lx-chrome>,
   so until that script runs the slot is 0px tall, everything below sits too
   high, and it all jumps when the real header lands. Measured on /women: a
   0.0799 shift on .lx-shop-main, most of that page's 0.1296 CLS. Reserving the
   height removed it entirely.

   145px is what the header occupies on a desktop — announcement bar, brand row
   and navigation band — and 92px below the breakpoint where the rail collapses
   into the drawer. The placeholder is REPLACED by outerHTML rather than filled,
   so these numbers stop applying the moment the real element exists; they only
   have to be right for the first few hundred milliseconds.

   The FOOTER slot is deliberately not reserved. It was tried: the footer
   measures 413px on a desktop and 1157px on a phone, and reserving both changed
   nothing — its two late shifts (0.0262 and 0.0224 on /women) survive the
   reservation, so the cause is inside the footer's own content settling, not an
   empty slot. Reserving it would have added a band of blank page for no gain. */
[data-lx-chrome="header"] { min-height: 145px; }

@media (max-width: 980px) {
  [data-lx-chrome="header"] { min-height: 92px; }
}

:where(.lx-shop) :where(h1, h2, h3, h4, p, figure, blockquote, dl, dd) { margin: 0; }
:where(.lx-shop) :where(img, svg, video) { display: block; max-width: 100%; }
:where(.lx-shop) :where(img) { height: auto; }

/* Zero specificity on purpose (:where): a form-control default that outranks
   .lx-btn silently repaints every button on the site with the body's colour and
   size — which is exactly what it did before this was wrapped. */
:where(.lx-shop) :where(button, input, select, textarea) {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
}

/* Only an UNCLASSED link — one inside running prose — takes the accent colour.
   Written with :where() so this rule carries the specificity of a bare `a`
   (0,0,1) and can never win against a component class like .lx-nav-link or
   .lx-dept. A base rule that outranks its own components is how a navigation
   ends up gold. */
:where(.lx-shop) a:where(:not([class])) { color: var(--gold); }
:where(.lx-shop) ::selection { background: var(--gold-wash-2); }

/* Money is set in the sans, and columns of it should line up. */
.lx-card-price, .lx-pdp-price, .lx-summary-row, .lx-bag-money,
.lx-listing-count, .lx-stickybuy-price {
  font-variant-numeric: tabular-nums;
}

/* ---- shared page furniture ---------------------------------------------- */

.lx-shop-main {
  min-height: 60vh;
}

.lx-wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.lx-section {
  padding-block: var(--section-y);
}

.lx-section--tight {
  padding-block: clamp(36px, 5vw, 64px);
}

/* A section announces itself with a hairline and a serif line above the goods,
   the way a printed page announces a chapter. The rule spans the full column so
   the eye gets a horizon before every shelf. */
.lx-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3) var(--s-6);
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-6);
  border-bottom: 1px solid var(--line);
}

.lx-section-title {
  font-family: var(--serif);
  font-size: clamp(24px, 2.6vw, 34px);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

/* "See all" is a quiet promise, not a call to action: small caps, ink, and a
   hairline that only appears under the pointer. */
.lx-section-link {
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-2);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  white-space: nowrap;
}

.lx-eyebrow {
  font-family: var(--sans);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 var(--s-2);
}

.lx-section-link { text-decoration: none; }
.lx-section-link:hover { color: var(--ink); border-bottom-color: var(--champagne); }

/* ---- ship-to control ----------------------------------------------------
   Deliberately part of the persistent chrome. The customer must always be able
   to see, and change, the country every price on the page depends on. */

.lx-shipto {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-meta);
  color: var(--ink-2);
}

.lx-shipto-label {
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

.lx-shipto-select {
  appearance: none;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink);
  font: inherit;
  padding: 4px 18px 4px 2px;
  min-height: 28px;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%),
                    linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
  background-position: right 6px center, right 1px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.lx-shipto-select:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* ---- product grid ------------------------------------------------------- */

.lx-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--card-gap);
}

@media (min-width: 720px)  { .lx-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .lx-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Five and six across on wider screens. Four columns held at every size above
   1080px, which on a 1366px laptop produced 281x445 cards — a card taller than
   half the viewport, so a row could never be seen whole. Narrower columns make
   the card shorter too, because the media box is a 4:5 ratio of its own width:
   at five across the same laptop gives roughly 245x400, and the row fits. */
@media (min-width: 1280px) { .lx-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (min-width: 1680px) { .lx-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

/* Homepage rows fetch six and show one complete row, whatever the grid
   resolved to. Scoped to [data-row] so a category or search listing — where
   every result must be shown — is untouched. */
[data-row] .lx-grid > *:nth-child(n+5) { display: none; }
@media (min-width: 1280px) { [data-row] .lx-grid > *:nth-child(5) { display: flex; } }
@media (min-width: 1680px) { [data-row] .lx-grid > *:nth-child(6) { display: flex; } }

.lx-grid--wide { grid-template-columns: repeat(1, minmax(0, 1fr)); }
@media (min-width: 720px) { .lx-grid--wide { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.lx-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  text-decoration: none;
  color: inherit;
}

/* The media sits on paper, not on the page's ivory: the product is the lit
   thing, and the warm page becomes the mount around it. */
.lx-card-media {
  display: block;
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--r-sm);
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--line);
}

.lx-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 1.2s var(--ease);
}

/* A slow, small drift. A 3% snap on hover reads as a web component; this reads
   as the photograph settling. */
.lx-card:hover .lx-card-media img { transform: scale(1.02); }
.lx-card:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }

/* Sample listings are labelled on the card, not only by the page banner:
   someone scrolling a grid should not have to remember which mode they are in
   to know what they are looking at. */
.lx-card-badge {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  padding: 6px 12px;
  border-radius: 0;
  background: var(--obsidian);
  color: var(--on-dark);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  line-height: 1.4;
}

/* A product with no photograph is a data problem, not a customer problem:
   the tile still holds its shape rather than collapsing the grid. */
.lx-card-noimage {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    -45deg, var(--ivory), var(--ivory) 12px, var(--porcelain) 12px, var(--porcelain) 24px
  );
}

.lx-card-body { display: flex; flex-direction: column; gap: 3px; }

.lx-card-brand {
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-3);
  line-height: 1.6;
}

/* The name is the loudest thing on the card, and it is set in the serif at a
   size that still lets four across a desktop row look like a row. */
.lx-card-title {
  font-family: var(--serif);
  font-size: var(--t-title-sm);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: 0.002em;
  color: var(--ink);
  text-wrap: balance;
}

.lx-card:hover .lx-card-title { text-decoration: underline; text-decoration-color: var(--champagne); text-underline-offset: 3px; }

.lx-card-price {
  margin-top: var(--s-2);
  font-size: var(--t-small);
  color: var(--ink-2);
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
}

.lx-card-was { color: var(--ink-4); text-decoration-thickness: 1px; }

/* ---- honest empty states ------------------------------------------------
   A curated catalogue is legitimately empty before its first product lands.
   That reads as a considered state, not a broken page. */

/* A dashed box says "component failed to load". A rule, a serif line and a lot
   of quiet says "there is nothing here yet, on purpose". */
.lx-empty {
  grid-column: 1 / -1;
  padding: var(--s-10) var(--s-5);
  text-align: center;
  color: var(--ink-2);
  font-family: var(--serif);
  font-size: clamp(19px, 2vw, 23px);
  line-height: 1.45;
  border: 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  margin: 0;
  max-width: 46ch;
  margin-inline: auto;
}

.lx-empty a, .lx-empty .lx-linkish {
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--champagne);
}

.lx-empty strong { display: block; color: var(--ink); font-weight: 400; margin-bottom: var(--s-3); }

/* ---- buttons ------------------------------------------------------------ */

/* Controls are plates, not pills: square, tracked, uppercase, and sized so the
   label has room to breathe. One geometry for every button on the site — the
   hero, the product page, the bag, checkout and the account — so a control is
   recognisable as a control anywhere. */
.lx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: var(--ctl-h);
  padding-inline: var(--ctl-px);
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  font-family: var(--sans);
  font-size: var(--t-button);
  font-weight: 500;
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}

.lx-btn--primary { background: var(--ink); color: var(--on-dark); }
.lx-btn--primary:hover { background: var(--obsidian-2); }

.lx-btn--ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.lx-btn--ghost:hover { background: var(--ink); color: var(--on-dark); }

/* A third weight for secondary actions that should not read as a second offer:
   a tracked label over a hairline, no box at all. */
.lx-btn--quiet {
  background: transparent;
  color: var(--ink-2);
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  min-height: 0;
  padding: var(--s-2) 0;
  border-radius: 0;
}

.lx-btn--quiet:hover { color: var(--ink); border-bottom-color: var(--ink); }

.lx-btn--block { width: 100%; }

.lx-btn[disabled], .lx-btn[aria-disabled='true'] {
  background: var(--disabled-bg);
  color: var(--disabled-ink);
  border-color: transparent;
  cursor: not-allowed;
}

.lx-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* Every focusable got a ring — verified by real Tab presses, not a scripted
   .focus() (which never matches :focus-visible and will tell you nothing is
   focusable). But only the controls with an explicit rule got the SITE's
   ring; the nav links, the department cards, the category tiles and all 30
   footer links fell through to the UA default, a 1px hairline that reads as
   a rendering artefact next to the 2px gold. `:where()` keeps this at zero
   specificity so any component rule still wins. */
:where(.lx-shop) :where(a, button, select, input, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* On a dark statement section the gold ring loses the contrast it has on
   porcelain, so those surfaces use the light-on-dark gold instead. The
   announcement bar is the only dark chrome the storefront has today; add any
   future --obsidian surface to this list rather than restating the ring. */
:where(.lx-announce) :where(a, button, select):focus-visible {
  outline-color: var(--gold-dark);
}

/* ---- hero ---------------------------------------------------------------
   The old hero was a headline, a paragraph and two buttons on an otherwise
   empty band — a page that had not started yet. This one is composed: the
   statement holds the left, the three departments hold the right, and the
   two columns finish at the same baseline so there is no dead corner.

   There is no hero photograph, and that is a decision rather than a gap. Until
   there is photography LuxScout owns, a stock image would be the single most
   dishonest element on the site. Type, rule and structure carry it instead. */

.lx-hero {
  position: relative;
  background: var(--ivory);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

/* The hero photograph is a 568px source, so the grid is sized around it rather
   than stretching it: at the widest, the image column lands near 600px, which
   is about 1.05x. Upscaling a soft flat-lay to 900px would look exactly like
   what it is. A higher-resolution original would let this run full-bleed. */
.lx-hero-inner {
  width: 100%;
  max-width: 1180px;
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  gap: var(--s-7);
  align-items: center;
  padding-block: clamp(40px, 6vw, 80px) 0;
}

@media (min-width: 900px) {
  .lx-hero-inner {
    grid-template-columns: 1fr minmax(0, 0.92fr);
    gap: clamp(32px, 4vw, 72px);
    padding-block: clamp(32px, 3.4vw, 52px) 0;
    min-height: 70vh;
  }
}

.lx-hero-copy h1 {
  font-family: var(--serif);
  font-size: var(--t-h1);
  font-weight: 400;
  line-height: var(--lh-tight);
  letter-spacing: -0.022em;
  color: var(--ink);
  margin: var(--s-5) 0 0;
  max-width: 13ch;
  text-wrap: balance;
}

/* `:not(.lx-eyebrow)` is load-bearing. `.lx-hero-copy p` is specificity
   (0,1,1) and `.lx-eyebrow` is (0,1,0), so this rule USED to win and the
   overline above the headline was set from the lede size instead of its own.
   Measured on the live homepage: 16px at 1366x900, 18px at 390px and 22px on
   a tall desktop — an eyebrow that changed size with the viewport HEIGHT,
   against the 11.5px it was written to be. The band eyebrow below rendered
   17px from the same cause, so the two overlines on one page never matched. */
.lx-hero-copy p:not(.lx-eyebrow) {
  font-size: var(--t-lede);
  line-height: 1.55;
  color: var(--ink-2);
  margin: var(--s-6) 0 0;
  max-width: 42ch;
  text-wrap: pretty;
}

.lx-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-top: var(--s-8);
  padding-bottom: clamp(40px, 5vw, 0px);
}

/* The drawing runs to the bottom edge of the band, so the hero ends on the
   artwork rather than on a margin. */
.lx-hero-art { margin: 0; align-self: end; }

.lx-hero-art img {
  width: 100%;
  max-width: 520px;
  height: auto;
  margin-inline: auto;
  display: block;
}

@media (min-width: 900px) {
  .lx-hero-art img { max-width: none; margin-inline: 0 auto; }
}

/* ---- hero, photographic --------------------------------------------------
   A full-bleed band with the photograph held to the right and the statement on
   a light panel over its left edge, which is how a department store front page
   reads: the goods first, the words on top of them.

   The band degrades on its own. `lx-hero--art` is set by home.js when the
   photograph 404s, and the layout falls back to the two-column drawing
   arrangement — no broken image, no empty grey rectangle, no build step. */
.lx-hero--photo {
  position: relative;
  background: var(--ivory);
  overflow: hidden;
  isolation: isolate;
}

.lx-hero-media { position: relative; }

.lx-hero-media img {
  width: 100%;
  height: 100%;
  /* `contain`, not `cover`. The hero photograph is a still life on a stone
     ledge — the bag fills the upper half, and the watch, the loafer and the
     flacon stand along the bottom edge. The media box is proportionally wider
     than the photograph, so `cover` fills the width and crops the height, and
     that strip comes off the bottom: on a laptop the watch was below the cut
     entirely. Cropping a product out of a shop's own hero is worse than
     showing the photograph smaller.

     `contain` scales it down to fit instead, so every object is visible at
     every band height. The space it leaves is the band's own ivory, which is
     the same studio backdrop the photograph was shot against, and the scrim
     above it covers the join. */
  object-fit: contain;
  object-position: right bottom;
  display: block;
}

.lx-hero--photo .lx-hero-inner { position: relative; z-index: 2; }

@media (min-width: 900px) {
  .lx-hero--photo { min-height: clamp(460px, 46vw, 620px); display: flex; align-items: center; }

  .lx-hero-media {
    position: absolute;
    inset: 0 0 0 20%;
    z-index: 1;
  }

  /* The scrim is a gradient of the page's own colour, not a black wash: the
     copy gets its contrast back without the photograph looking dimmed. */
  .lx-hero-media::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to right,
      var(--ivory) 0%, var(--ivory) 22%,
      rgba(244, 241, 233, 0.88) 38%, rgba(244, 241, 233, 0.45) 52%,
      rgba(244, 241, 233, 0) 68%);
  }

  .lx-hero--photo .lx-hero-inner {
    display: block;
    padding-block: clamp(48px, 6vw, 88px);
    min-height: 0;
  }

  .lx-hero--photo .lx-hero-copy { max-width: 34rem; }
}

/* A hero sized only from the viewport's WIDTH will happily eat a laptop's
   whole screen. Measured on the live site at 1366x768: the band stood 716px
   tall in a 768px viewport — 93% of it — the first product row began at
   y=971, and a shopper had to scroll 888px before one complete product card
   was visible. The page read as a poster, and nothing on the first screen
   suggested a shop continued below it.

   So on a short viewport the hero is capped by the height available as well
   as the width. This block contains ONLY the override: an earlier version put
   the whole desktop hero inside it, which quietly took `position: absolute`
   away from .lx-hero-media on any screen taller than 920px and would have
   broken the band on a desktop monitor. A media query that also carries the
   rules it is meant to adjust is how that happens.

   `svh` is the small viewport height, stable on phones where browser chrome
   collapses on scroll; the vh line before it is the fallback for engines that
   do not know svh. 300px leaves room for the announcement bar, the header and
   enough of the next section to show the page continues. */
@media (min-width: 900px) and (max-height: 920px) {
  .lx-hero--photo { min-height: min(clamp(400px, 40vw, 620px), calc(100vh - 300px)); }
  .lx-hero--photo { min-height: min(clamp(400px, 40vw, 620px), calc(100svh - 300px)); }

  /* Capping the band was not enough on its own, and measuring showed why: the
     band was 716px on a 768px laptop while its min-height resolved to 468,
     so the height was never coming from min-height at all. `.lx-hero-inner`
     carries `min-height: 70vh` — 538px there — and the photo band adds
     clamp(48px, 6vw, 88px) of padding top and bottom on top of it. 538 + 162
     is the 716 that was measured. The image was never the cause. */
  .lx-hero-inner { min-height: 0; }
  .lx-hero--photo .lx-hero-inner { padding-block: clamp(24px, 2.4vw, 40px); }

  /* And the copy itself, which is what remained after the padding came down.
     The display size is set from viewport WIDTH, so a wide-but-short laptop
     gets the same 56px headline a 27-inch monitor does, over three lines,
     with a lede and two buttons under it. Scaled to the height available, the
     band clears the fold and the shopper can see there is a shop below it. */
  .lx-hero-copy h1 { font-size: clamp(30px, 3.4vw, 46px); margin-top: var(--s-3); }
  .lx-hero-copy p:not(.lx-eyebrow) { font-size: 1rem; margin-top: var(--s-4); }
  .lx-hero-actions { margin-top: var(--s-5); }
}

/* On a phone the photograph sits under the copy at a workable height instead of
   being cropped to a letterbox behind text. */
@media (max-width: 899px) {
  .lx-hero--photo { display: flex; flex-direction: column-reverse; }
  .lx-hero-media { aspect-ratio: 4 / 3; }
  .lx-hero--photo .lx-hero-inner { padding-block: clamp(32px, 7vw, 48px); }
}

/* Fallback: no photograph on the server, so the drawing runs in the old
   two-column arrangement. */
.lx-hero--art .lx-hero-media { position: static; inset: auto; aspect-ratio: auto; }
.lx-hero--art .lx-hero-media::after { display: none; }
.lx-hero--art .lx-hero-media img { object-fit: contain; max-height: 560px; }

@media (min-width: 900px) {
  .lx-hero--art { display: grid; grid-template-columns: 1fr minmax(0, 0.92fr); align-items: center; }
  .lx-hero--art .lx-hero-media { order: 2; }
  .lx-hero--art .lx-hero-inner { order: 1; padding-inline-end: 0; }
}

/* ---- departments --------------------------------------------------------
   Three doors, side by side, under the hero. Hairline-separated rather than
   boxed: a card with a border and a shadow is a component; a column with a
   rule between it and its neighbour is a page. */
.lx-depts {
  display: grid;
  grid-template-columns: 1fr;
  border-bottom: 1px solid var(--line);
}

@media (min-width: 760px) { .lx-depts { grid-template-columns: repeat(3, 1fr); } }

.lx-dept {
  position: relative;
  display: block;
  padding: clamp(28px, 3.4vw, 48px) 0;
  padding-inline-end: var(--s-7);
  text-decoration: none;
  color: var(--ink);
  border-top: 1px solid var(--line);
  overflow: hidden;
}

@media (min-width: 760px) {
  .lx-dept { border-top: 0; padding-inline: 0 var(--s-8); }
  .lx-dept + .lx-dept { border-left: 1px solid var(--line); padding-inline-start: clamp(24px, 3vw, 48px); }
}

/* A department card with a photograph behind it: the image fills the card, a
   scrim carries the type, and the hairline dividers between the plain cards are
   dropped because the frames provide their own edges. */
.lx-dept.has-photo {
  border: 0;
  padding: 0;
  color: var(--on-dark);
  min-height: clamp(300px, 30vw, 380px);
  display: flex;
  align-items: flex-end;
}

.lx-depts:has(.has-photo) { border-bottom: 0; gap: var(--card-gap); }
.lx-dept.has-photo + .lx-dept.has-photo { border-left: 0; padding-inline-start: 0; }

.lx-dept-media { display: none; }

.has-photo .lx-dept-media {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--ivory);
}

.has-photo .lx-dept-media img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.4s var(--ease); }
.has-photo:hover .lx-dept-media img { transform: scale(1.03); }

.has-photo .lx-dept-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(20, 17, 11, 0.72) 0%, rgba(20, 17, 11, 0.34) 46%, rgba(20, 17, 11, 0.06) 100%);
}

.has-photo .lx-dept-body {
  position: relative;
  z-index: 1;
  padding: clamp(20px, 2.4vw, 32px);
}

.has-photo .lx-dept-name { color: var(--on-dark); }
/* Measured: "Clothing, shoes, bags, accessories, watches, eyewear and
   fragrance" set three lines with "fragrance" alone on the last at every
   desktop width. `pretty` is the right tool rather than `balance` - it
   pulls a word down to kill the widow without evening out the lines above,
   which is what a running note wants and a headline does not. */
.lx-dept-note { text-wrap: pretty; }
.has-photo .lx-dept-note { color: rgba(242, 238, 228, 0.86); }
.has-photo .lx-dept-go { color: var(--on-dark); border-bottom-color: var(--gold-dark); }
.has-photo:hover .lx-dept-go { color: var(--gold-dark); border-bottom-color: var(--gold-dark); }

.lx-dept:hover .lx-dept-go { color: var(--ink); border-bottom-color: var(--ink); }
.lx-dept:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }

/* ---- editorial band ------------------------------------------------------
   A full-width statement over the house drawing. The copy sits in the left
   third, which is the part of the artwork deliberately left empty. */
/* The drawing is anchored to the right edge at its own aspect ratio rather than
   covering the band: `cover` crops the empty left third the artwork was
   composed with, and walks the objects underneath the copy. */
.lx-band {
  background-color: var(--porcelain);
  border-block: 1px solid var(--line);
}

.lx-band-inner {
  display: grid;
  width: 100%;
  gap: var(--s-8);
  align-items: center;
  padding-block: clamp(56px, 7vw, 96px);
}

@media (min-width: 900px) {
  .lx-band-inner { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr); gap: clamp(32px, 5vw, 80px); }
}

.lx-band-art { margin: 0; }
.lx-band-art img { width: 100%; height: auto; }

/* On a phone the drawing sits under the copy at a workable height rather than
   being squeezed into a 100px strip. */
@media (max-width: 899px) {
  .lx-band-art img { max-height: 220px; object-fit: contain; object-position: right bottom; }
}

.lx-band-copy { max-width: 46ch; }

/* `text-wrap: balance` is not decoration here. Measured on the live
   homepage at 1280, 1366, 1440, 1512 and 1920px, this headline broke as
   "Specification first, then the" / "price." every single time - one
   six-letter word alone on the second line of the largest heading on the
   page, at 20% of the block width. The hero's h1 has carried `balance`
   since it was written and was the ONLY multi-line heading on the site
   that measured clean; it was simply never applied anywhere else. */
.lx-band-copy h2 {
  font-family: var(--serif);
  font-size: clamp(28px, 3.6vw, 46px);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.018em;
  margin: var(--s-4) 0 var(--s-5);
  color: var(--ink);
  text-wrap: balance;
}

/* Same (0,1,1) vs (0,1,0) trap as .lx-hero-copy p — see the note there. */
.lx-band-copy p:not(.lx-eyebrow) {
  font-size: var(--t-body);
  line-height: 1.65;
  color: var(--ink-2);
  margin: 0 0 var(--s-7);
  text-wrap: pretty;
}

/* A row lede — one line of context under a section head, used by the
   merchandised rows on the homepage. */
.lx-section-lede {
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink-2);
  margin: calc(var(--s-6) * -1) 0 var(--s-7);
  max-width: 56ch;
  text-wrap: pretty;
}

/* ---- assurance strip ----------------------------------------------------
   Four statements directly under the hero, each describing something the
   platform does. Nothing here is a promise the system cannot keep. */
.lx-assure {
  display: grid;
  gap: var(--s-4) var(--s-6);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  padding-block: var(--s-6);
  border-bottom: 1px solid var(--line);
}

@media (min-width: 900px) { .lx-assure { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.lx-assure-item {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--s-3);
  row-gap: 2px;
  align-items: start;
}

.lx-assure-icon { grid-row: 1 / span 2; color: var(--ink-2); }
.lx-assure-icon svg { width: 26px; height: 26px; }
.lx-assure-item b, .lx-assure-item > span:not(.lx-assure-icon) { grid-column: 2; }
.lx-assure-item b { font-size: var(--t-small); font-weight: 500; color: var(--ink); }
.lx-assure-item span { font-size: var(--t-meta); color: var(--ink-2); line-height: 1.5; }

/* ---- launch state -------------------------------------------------------
   What the homepage shows when the catalogue has nothing for this market. It
   describes the range LuxScout is opening with — which is true, specific and
   useful — instead of apologising for an empty page or narrating the internal
   work of building a catalogue. */
.lx-launch { padding-block: var(--section-y) 0; }

.lx-launch-grid {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: repeat(1, minmax(0, 1fr));
  margin-top: var(--s-7);
}

@media (min-width: 720px)  { .lx-launch-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .lx-launch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.lx-launch-item {
  display: block;
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
  text-decoration: none;
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease);
}

.lx-launch-item:hover { border-color: var(--champagne); }
.lx-launch-item h3 { font-family: var(--serif); font-size: var(--t-title); font-weight: 500; margin: 0 0 var(--s-2); }
.lx-launch-item p { font-size: var(--t-small); line-height: 1.6; color: var(--ink-2); margin: 0; }

/* ---- category rail ------------------------------------------------------ */

/* Category tiles carry the house drawings, so they are image-led like the
   product grid rather than a row of bordered boxes with a count in them. */
.lx-rail {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--card-gap);
}

@media (min-width: 720px)  { .lx-rail { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .lx-rail { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.lx-rail-item {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  text-decoration: none;
  color: var(--ink);
  padding: 0;
  border: 0;
  background: transparent;
}

.lx-rail-media {
  display: block;
  /* 5:4, not 4:5. The category photographs are landscape (265x218), so a
     portrait box cropped the sides off every one of them AND made the
     section the tallest block on the page — 1,175px measured, two rows of
     400px-tall tiles. This matches the photography and takes roughly 300px
     out of the section without losing a tile. */
  aspect-ratio: 5 / 4;
  overflow: hidden;
  background: var(--ivory);
  box-shadow: inset 0 0 0 1px var(--line);
}

.lx-rail-media img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--ease); }
.lx-rail-item:hover .lx-rail-media img { transform: scale(1.02); }

.lx-rail-body { display: flex; flex-direction: column; gap: 3px; }
.lx-rail-name { font-family: var(--serif); font-size: var(--t-title); line-height: 1.2; }
.lx-rail-item:hover .lx-rail-name { text-decoration: underline; text-decoration-color: var(--champagne); text-underline-offset: 3px; }
.lx-rail-count { font-size: var(--t-meta); color: var(--ink-3); letter-spacing: 0.02em; }
.lx-rail-item:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }

/* ---- product page ------------------------------------------------------- */

.lx-pdp {
  display: grid;
  gap: var(--s-7);
  padding-block: var(--s-7) var(--section-y);
}

@media (min-width: 900px) {
  .lx-pdp { grid-template-columns: minmax(0, 1.15fr) minmax(340px, 0.85fr); gap: clamp(32px, 5vw, 72px); align-items: start; }
  .lx-pdp-buy { position: sticky; top: 96px; }
}

.lx-gallery { display: grid; gap: var(--s-3); }

.lx-gallery-main {
  aspect-ratio: 4 / 5;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--ivory);
}

.lx-gallery-main img { width: 100%; height: 100%; object-fit: cover; display: block; }

.lx-gallery-thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: var(--s-2);
}

.lx-thumb {
  aspect-ratio: 1;
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  overflow: hidden;
  background: var(--ivory);
  padding: 0;
  cursor: pointer;
}

.lx-thumb[aria-current='true'] { border-color: var(--ink); }
.lx-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.lx-pdp-brand {
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 var(--s-2);
}

.lx-pdp-title {
  font-family: var(--serif);
  font-size: clamp(28px, 3.2vw, 40px);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 var(--s-4);
  text-wrap: balance;
}

/* The price is stated once, plainly, in the sans. It does not need to be
   bigger than the name of the thing. */
.lx-pdp-price {
  font-size: var(--t-title-sm);
  color: var(--ink);
  margin: 0 0 var(--s-6);
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--line);
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
}

.lx-pdp-price s { font-size: var(--t-small); color: var(--ink-4); }

/* ---- variant selectors -------------------------------------------------- */

.lx-options { display: grid; gap: var(--s-5); margin-bottom: var(--s-5); }

.lx-option-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-3);
}

.lx-option-values { display: flex; flex-wrap: wrap; gap: var(--s-2); }

.lx-swatch {
  min-height: var(--ctl-h-sm);
  min-width: var(--tap);
  padding-inline: var(--ctl-px-sm);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-small);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease);
}

.lx-swatch:hover { border-color: var(--ink-3); }
.lx-swatch[aria-pressed='true'] { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }

/* An unavailable size is shown and disabled, never hidden: a customer who
   wears it deserves to know it exists and is out, not to wonder. */
.lx-swatch[disabled] {
  color: var(--ink-4);
  border-color: var(--line);
  cursor: not-allowed;
  background:
    linear-gradient(to top left,
      transparent calc(50% - 0.5px), var(--line-strong) 50%, transparent calc(50% + 0.5px));
}

.lx-size-guide-link {
  font-size: var(--t-meta);
  color: var(--gold);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
}

/* ---- availability + delivery -------------------------------------------- */

.lx-availability {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-small);
  margin-bottom: var(--s-4);
}

.lx-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.lx-dot--in { background: var(--success); }
.lx-dot--low { background: var(--warning); }
.lx-dot--out { background: var(--ink-4); }

.lx-availability--in { color: var(--success); }
.lx-availability--low { color: var(--warning); }
.lx-availability--out { color: var(--ink-3); }

.lx-delivery {
  font-size: var(--t-small);
  color: var(--ink-2);
  padding: var(--s-3) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-5);
}

.lx-delivery b { font-weight: 500; color: var(--ink); }

/* ---- accordion details -------------------------------------------------- */

.lx-details { margin-top: var(--s-7); border-top: 1px solid var(--line); }

.lx-details details { border-bottom: 1px solid var(--line); }

.lx-details summary {
  cursor: pointer;
  padding: var(--s-4) 0;
  font-size: var(--t-small);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.lx-details summary::-webkit-details-marker { display: none; }
.lx-details summary::after { content: '+'; color: var(--ink-3); font-size: 18px; }
.lx-details details[open] summary::after { content: '–'; }

.lx-details-body {
  padding-bottom: var(--s-5);
  font-size: var(--t-small);
  line-height: var(--lh-body);
  color: var(--ink-2);
}

.lx-details-body p { margin: 0 0 var(--s-3); }
.lx-details-body dl { display: grid; grid-template-columns: minmax(120px, auto) 1fr; gap: var(--s-2) var(--s-5); margin: 0; }
.lx-details-body dt { color: var(--ink-3); }
.lx-details-body dd { margin: 0; color: var(--ink); }
.lx-details-body ul { margin: 0; padding-left: 1.1em; }

/* ---- bag ---------------------------------------------------------------- */

.lx-bag { display: grid; gap: var(--s-7); padding-block: var(--s-7) var(--section-y); }

@media (min-width: 900px) {
  .lx-bag { grid-template-columns: minmax(0, 1.4fr) minmax(320px, 0.6fr); gap: clamp(32px, 5vw, 64px); align-items: start; }
  .lx-bag-summary { position: sticky; top: 96px; }
}

.lx-bag-line {
  display: grid;
  grid-template-columns: 88px 1fr auto;
  gap: var(--s-4);
  padding: var(--s-5) 0;
  border-bottom: 1px solid var(--line);
  align-items: start;
}

.lx-bag-thumb {
  aspect-ratio: 4 / 5;
  border-radius: var(--r-xs);
  overflow: hidden;
  background: var(--ivory);
}

.lx-bag-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.lx-bag-title { font-family: var(--serif); font-size: var(--t-title-xs); color: var(--ink); margin: 0 0 2px; }
.lx-bag-variant { font-size: var(--t-meta); color: var(--ink-3); margin: 0 0 var(--s-3); }

.lx-qty { display: inline-flex; align-items: center; border: 1px solid var(--line-strong); border-radius: var(--r-sm); }

.lx-qty button {
  position: relative;
  width: 34px; height: 34px;
  border: 0; background: transparent; cursor: pointer;
  color: var(--ink); font-size: 16px; line-height: 1;
}

/* 34px keeps the stepper visually compact inside its border, but 34px is
   under the 44px floor --tap sets. The hit area — the thing the floor is
   about — is extended invisibly; the count sits between the buttons, so the
   extra 5px a side never overlaps the other button. */
.lx-qty button::after { content: ''; position: absolute; inset: -5px; }

/* --disabled-ink, not --ink-4: a disabled control is exempt from the contrast
   floor precisely because dimming it is how a user knows it is disabled. */
.lx-qty button:disabled { color: var(--disabled-ink); cursor: not-allowed; }
.lx-qty output { min-width: 28px; text-align: center; font-size: var(--t-small); }

.lx-bag-remove {
  background: none; border: 0; padding: 0; margin-left: var(--s-4);
  font-size: var(--t-meta); color: var(--ink-3); cursor: pointer; text-decoration: underline;
}

.lx-bag-summary {
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s-6);
  background: var(--paper);
}

.lx-summary-row {
  display: flex; justify-content: space-between; gap: var(--s-4);
  font-size: var(--t-small); color: var(--ink-2); padding-block: var(--s-2);
}

.lx-summary-row--total {
  border-top: 1px solid var(--line);
  margin-top: var(--s-3); padding-top: var(--s-4);
  font-size: var(--t-body); color: var(--ink); font-weight: 500;
}

.lx-summary-note { font-size: var(--t-meta); color: var(--ink-3); margin: var(--s-3) 0 0; }

/* ---- problems -----------------------------------------------------------
   The bag says exactly what is wrong and with which item. A blocked checkout
   is never a silent disabled button. */

.lx-problems { margin: 0 0 var(--s-5); padding: 0; list-style: none; display: grid; gap: var(--s-2); }

.lx-problem {
  display: flex; gap: var(--s-3); align-items: flex-start;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-sm);
  font-size: var(--t-small);
  background: var(--warning-wash);
  color: var(--ink);
  border: 1px solid transparent;
}

.lx-problem--blocking { background: var(--danger-wash); }

/* ---- checkout ----------------------------------------------------------- */

.lx-checkout { display: grid; gap: var(--s-7); padding-block: var(--s-7) var(--section-y); }

@media (min-width: 900px) {
  .lx-checkout { grid-template-columns: minmax(0, 1.2fr) minmax(320px, 0.8fr); gap: clamp(32px, 5vw, 64px); align-items: start; }
  .lx-checkout-summary { position: sticky; top: 96px; }
}

.lx-fieldset { border: 0; padding: 0; margin: 0 0 var(--s-7); }

.lx-fieldset legend {
  font-family: var(--serif);
  font-size: var(--t-title);
  color: var(--ink);
  padding: 0;
  margin-bottom: var(--s-4);
}

.lx-fields { display: grid; gap: var(--s-4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.lx-field--full { grid-column: 1 / -1; }

@media (max-width: 640px) { .lx-fields { grid-template-columns: 1fr; } }

.lx-field label {
  display: block;
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-2);
}

.lx-field input, .lx-field select, .lx-field textarea {
  width: 100%;
  min-height: var(--ctl-h);
  padding: 10px var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-body-app);
}

.lx-field input:focus-visible, .lx-field select:focus-visible, .lx-field textarea:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}

.lx-field-error { font-size: var(--t-meta); color: var(--danger); margin-top: var(--s-1); }

#lx-payment-element { margin-block: var(--s-4); }

.lx-secure-note {
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--t-meta); color: var(--ink-3); margin-top: var(--s-4);
}

/* ---- order confirmation ------------------------------------------------- */

.lx-order-head { text-align: center; padding-block: var(--section-y) var(--s-7); }
.lx-order-head h1 { font-family: var(--serif); font-size: var(--t-h2); font-weight: 500; margin: 0 0 var(--s-3); color: var(--ink); }
.lx-order-head p { color: var(--ink-2); margin: 0; }

.lx-timeline { list-style: none; margin: var(--s-7) 0 0; padding: 0; display: grid; gap: var(--s-4); }

.lx-timeline li {
  display: grid; grid-template-columns: 20px 1fr; gap: var(--s-3);
  font-size: var(--t-small); color: var(--ink-2);
}

.lx-timeline-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line-strong); margin-top: 6px; }
.lx-timeline li.is-done .lx-timeline-dot { background: var(--success); }
.lx-timeline li.is-current .lx-timeline-dot { background: var(--gold); box-shadow: 0 0 0 4px var(--gold-wash); }
.lx-timeline-when { display: block; font-size: var(--t-meta); color: var(--ink-4); }

/* ---- trust strip (facts only) ------------------------------------------- */

.lx-trust {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-5);
  padding-block: var(--section-y);
  border-top: 1px solid var(--line);
}

@media (min-width: 900px) { .lx-trust { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.lx-trust-item h3 {
  font-size: var(--t-small);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 var(--s-2);
  font-weight: 500;
}

.lx-trust-item p { font-size: var(--t-small); line-height: 1.6; color: var(--ink-2); margin: 0; }

/* ---- skeletons ---------------------------------------------------------- */

.lx-skeleton {
  background: linear-gradient(90deg, var(--ivory) 25%, var(--porcelain) 50%, var(--ivory) 75%);
  background-size: 200% 100%;
  animation: lx-shimmer 1.4s infinite;
  border-radius: var(--r-sm);
}

.lx-skeleton-card { aspect-ratio: 4 / 5; }

@keyframes lx-shimmer {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .lx-skeleton { animation: none; }
}

/* ---- visually hidden ---------------------------------------------------- */

.lx-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* THE SKIP LINK HAS TO BE SEEN TO BE USED.
   "Skip to content" is the first Tab stop on every page and it was staying
   1x1 and clipped when focused — measured at 390px: 1x1 at top:-1, no
   background, and the UA's default link blue, because nothing ever styled it.
   A keyboard user pressing Tab saw nothing happen and had no way to know the
   shortcut was there, which is the whole of SC 2.4.1 and SC 2.4.7.

   Only the skip link can match this: .lx-sr is also the generic
   visually-hidden utility, but it is otherwise applied to spans that carry a
   hint for a screen reader, and a span is not focusable. */
.lx-sr:focus {
  position: fixed;
  top: var(--s-3);
  left: var(--s-3);
  z-index: 200;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
  clip-path: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--ctl-h);
  padding-inline: var(--ctl-px);
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: var(--shadow-pop);
  font-size: var(--t-button);
  font-weight: 500;
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  text-decoration: none;
}

/* ==========================================================================
   STORE CHROME — header, navigation, drawer, footer
   ==========================================================================
   Injected by shop-chrome.js. The header is quiet by default and solidifies on
   scroll so it stays legible over photography without a permanently heavy bar.
   ========================================================================== */

.lx-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--porcelain);
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
  border-bottom: 1px solid transparent;
}

.lx-header.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-sm);
}

.lx-topbar {
  border-bottom: 1px solid var(--line);
  background: var(--ivory);
}

/* Three columns, the middle one centred on the PAGE rather than on the space
   left over, so the wordmark sits dead centre whatever the ship-to control and
   the icons happen to measure. */
.lx-topbar-inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--s-4);
  min-height: 56px;
}

.lx-topbar-left { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }

.lx-topbar-note { display: none; }

.lx-brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  text-decoration: none;
  color: var(--ink);
  flex: none;
}

.lx-brand-mark { color: var(--champagne); flex: none; }
/* The <picture> that offers the mark as WebP is the flex item now, so it
   carries the sizing the img used to. */
.lx-brand-pic { display: inline-flex; flex: none; }
.lx-brand:hover .lx-brand-mark { color: var(--gold); }

.lx-brand-word {
  font-family: var(--serif);
  font-weight: 500;
  text-transform: uppercase;
  line-height: 1;
}

/* The mark is hidden on a phone (see .lx-brand--header .lx-brand-mark below),
   so the link collapses to the height of the wordmark alone — measured 19px
   at 390px, under WCAG 2.2 SC 2.5.8's 24px. The header row is already 44px
   tall because the icon buttons are, so claiming that height costs no layout
   and gives the home link the same target every other control has. */
.lx-brand--header { grid-column: 2; min-height: var(--tap); }
.lx-brand--header .lx-brand-word { font-size: clamp(19px, 1.9vw, 24px); letter-spacing: 0.18em; padding-left: 0.18em; }
/* The monogram is redundant beside the word it abbreviates; it stays as the
   favicon, the touch icon and the share image, where the word will not fit. */
/* Both, not just the img: the mark is offered through a <picture>, which is
   itself a flex item of .lx-brand. Hiding the image alone would leave an empty
   element and its var(--s-3) gap in front of the wordmark. */
.lx-brand--header .lx-brand-mark,
.lx-brand--header .lx-brand-pic { display: none; }
.lx-brand--footer .lx-brand-word { font-size: var(--t-title-lg); letter-spacing: 0.16em; padding-left: 0.16em; }

/* The navigation is a band of its own under the name, centred, with a hairline
   above it. */
.lx-navbar { border-top: 1px solid var(--line); background: var(--porcelain); }

.lx-navbar .lx-nav {
  justify-content: center;
  min-height: 48px;
  margin-inline: auto;
}

/* Once the page scrolls, the utility bar folds away and only the navigation
   rides along — the shop stays reachable without a 2-row bar following the
   reader down the page. */
.lx-header.is-stuck .lx-topbar { display: none; }

/* Eleven destinations have to fit on one line without the header feeling like
   a toolbar. The gap is tight, the type stays small, and the whole rail hands
   over to the drawer at 1180px rather than trying to survive at 1080. */
.lx-nav {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  margin-inline: auto;
  flex-wrap: nowrap;
  overflow: visible;
}

/* Navigation is set as tracked small caps — the same language as every other
   label on the site, so the header reads as part of the system rather than as
   a browser toolbar. */
.lx-nav-link {
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-2);
  text-decoration: none;
  padding-block: 8px;
  border-bottom: 1px solid transparent;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease);
}

.lx-nav-link:hover { color: var(--ink); }
.lx-nav-link[aria-current='page'] { color: var(--ink); border-bottom-color: var(--ink); }
.lx-nav-new { color: var(--ink); }
.lx-nav-sep { width: 1px; height: 14px; background: var(--line-strong); flex: none; }

/* ---- nav panels ---------------------------------------------------------
   Women, Men, Kids and Accessories open a short column of what is underneath
   them. The panel is anchored to its item rather than spanning the viewport:
   a full-width mega menu for four links is a lot of curtain for a small
   window. */
.lx-nav-item { position: relative; display: inline-flex; align-items: center; gap: 2px; }

/* Measured live at 1366px: 20x20. WCAG 2.2 SC 2.5.8 (Target Size, Minimum)
   asks for 24x24 CSS px and this missed it in both axes. The chevron itself
   stays 14px — only the box it sits in grew, so the header rhythm is
   unchanged. The rail collapses into the drawer below 980px, so this control
   is pointer-only; it is sized for SC 2.5.8, not for a thumb. */
.lx-nav-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  border-radius: var(--r-xs);
}

.lx-nav-more svg { width: 14px; height: 14px; transition: transform var(--dur-fast) var(--ease); }
.lx-nav-item.is-open .lx-nav-more svg { transform: rotate(180deg); }
.lx-nav-more:hover { color: var(--ink); }
.lx-nav-more:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }

.lx-nav-panel {
  position: absolute;
  top: calc(100% + 14px);
  left: -14px;
  z-index: 50;
  min-width: 210px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-pop);
}

.lx-nav-panel[hidden] { display: none; }

/* A hover bridge: the 14px gap above would otherwise close the panel as the
   pointer travelled into it. */
.lx-nav-panel::before {
  content: '';
  position: absolute;
  inset: -16px 0 100% 0;
}

.lx-nav-panel-inner { display: flex; flex-direction: column; padding: var(--s-3); }

.lx-nav-panel-link,
.lx-nav-panel-all {
  font-size: var(--t-small);
  color: var(--ink-2);
  text-decoration: none;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  white-space: nowrap;
}

.lx-nav-panel-link:hover,
.lx-nav-panel-all:hover { background: var(--gold-wash); color: var(--ink); }

.lx-nav-panel-all {
  color: var(--ink);
  font-weight: 500;
  border-bottom: 1px solid var(--line);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  margin-bottom: var(--s-1);
}

.lx-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.lx-header-actions {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  grid-column: 3;
  justify-self: end;
  flex: none;
}

.lx-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  border: 0;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  border-radius: var(--r-sm);
  position: relative;
  text-decoration: none;
}

.lx-icon-btn svg { width: var(--icon-lg); height: var(--icon-lg); }
.lx-icon-btn:hover { background: var(--gold-wash); }
.lx-icon-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }

.lx-bag-count {
  position: absolute;
  top: 6px;
  right: 4px;
  min-width: 17px;
  height: 17px;
  padding-inline: 4px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--on-dark);
  font-size: 10.5px;
  line-height: 17px;
  text-align: center;
  font-family: var(--sans);
}

.lx-bag-count.is-empty { display: none; }

/* The nav rail collapses to the drawer well before it would wrap: a shop
   header that reflows onto two lines reads as broken on a phone. */
.lx-nav-toggle { display: none; }

/* The menu button lives in the utility bar next to the ship-to control, and
   only appears when the navigation rail hands over to the drawer. */
.lx-nav-toggle { display: none; margin-left: -10px; }

@media (max-width: 1180px) {
  .lx-navbar { display: none; }
  .lx-nav-toggle { display: inline-flex; }
  .lx-header.is-stuck .lx-topbar { display: block; }
}

/* On a phone the ship-to control moves into the drawer, where it has room to
   be a real control rather than a squeezed select between two icons. */
@media (max-width: 720px) {
  .lx-topbar-left [data-shipto] { display: none; }
  .lx-topbar-inner { min-height: 52px; }
}

/* ---- drawer ------------------------------------------------------------- */

.lx-drawer {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--porcelain);
  overflow-y: auto;
  padding-bottom: var(--s-9);
}

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

html.lx-drawer-open, html.lx-drawer-open body { overflow: hidden; }

.lx-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-4) var(--gutter);
  border-bottom: 1px solid var(--line);
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
}

.lx-drawer-nav { display: flex; flex-direction: column; padding: var(--s-5) var(--gutter); }

.lx-drawer-link,
.lx-drawer-toggle {
  font-family: var(--serif);
  font-size: 22px;
  color: var(--ink);
  text-decoration: none;
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--line);
  min-height: var(--tap);
}

/* An accordion, not a flat list of nineteen links: on a phone the thing you
   want should be one scroll away, not eleven. */
.lx-drawer-group-item { display: flex; flex-direction: column; }

.lx-drawer-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  width: 100%;
  background: transparent;
  border-inline: 0;
  border-top: 0;
  text-align: left;
  cursor: pointer;
}

.lx-drawer-toggle svg { width: 20px; height: 20px; color: var(--ink-3); transition: transform var(--dur-fast) var(--ease); }
.lx-drawer-toggle[aria-expanded='true'] svg { transform: rotate(180deg); }
.lx-drawer-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }

.lx-drawer-sub { display: flex; flex-direction: column; padding: var(--s-2) 0 var(--s-4) var(--s-4); }
.lx-drawer-sub[hidden] { display: none; }

.lx-drawer-sub a {
  font-family: var(--sans);
  font-size: var(--t-body);
  color: var(--ink-2);
  text-decoration: none;
  padding-block: var(--s-3);
  min-height: var(--tap);
  display: flex;
  align-items: center;
}

.lx-drawer-sub a:first-child { color: var(--ink); font-weight: 500; }

.lx-drawer-link--lead { color: var(--ink); }

.lx-drawer-shipto { display: block; margin-top: var(--s-6); }

.lx-drawer-group {
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: var(--s-6) 0 var(--s-2);
}

/* ---- preview bar --------------------------------------------------------
   Shown only in preview mode, and deliberately impossible to miss. A preview
   that looks like the shop is worse than no preview. */
.lx-preview-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  padding: var(--s-3) var(--gutter);
  background: var(--obsidian);
  color: var(--on-dark);
  font-size: var(--t-small);
  line-height: 1.5;
  text-align: center;
}

.lx-preview-bar b { color: var(--gold-dark); font-weight: 500; }

.lx-preview-exit {
  flex: none;
  border: 1px solid var(--line-dark);
  background: transparent;
  color: var(--on-dark);
  font-family: var(--sans);
  font-size: var(--t-button);
  padding: 10px 18px;
  border-radius: var(--r-sm);
  font-size: var(--t-label);
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  cursor: pointer;
  min-height: 38px;
}

.lx-preview-exit:hover { border-color: var(--gold-dark); color: var(--gold-dark); }
.lx-preview-exit:focus-visible { outline: 2px solid var(--gold-dark); outline-offset: 2px; }

/* Keep the bar off the last row of content. */
html.lx-has-preview-bar body { padding-bottom: 76px; }

/* On a phone the product page pins its own buy bar to the bottom, and in
   preview mode both would occupy the same strip — the preview bar has the
   higher z-index, so it would sit on top of Add to Bag and hide it. Lift the
   buy bar above it instead of letting them fight. */
html.lx-has-preview-bar .lx-stickybuy { bottom: 72px; }

@media (max-width: 640px) {
  /* Two lines of copy plus a button is tall on a narrow screen, so the bar
     gives the content more room back. */
  html.lx-has-preview-bar body { padding-bottom: 116px; }
  html.lx-has-preview-bar .lx-stickybuy { bottom: 108px; }
  .lx-preview-bar { text-align: left; justify-content: space-between; }
}

/* ---- footer ------------------------------------------------------------- */

.lx-footer {
  border-top: 1px solid var(--line);
  background: var(--ivory);
  margin-top: var(--section-y);
}

.lx-footer-inner {
  display: grid;
  gap: var(--s-6);
  /* The footer is a landing place, not a section of its own: a full
     --section-y above the columns made the block taller than its content. */
  padding-block: clamp(40px, 5vw, 64px) var(--s-6);
  grid-template-columns: 1fr;
}

/* Shop carries two link columns, so it takes the width of two link stacks. */
@media (min-width: 720px) {
  .lx-footer-inner { grid-template-columns: 1.5fr 1.4fr 1fr 1fr; gap: var(--s-7); }
}

.lx-footer-brand p {
  font-size: var(--t-small);
  line-height: var(--lh-body);
  color: var(--ink-2);
  margin: var(--s-3) 0 var(--s-4);
  max-width: 44ch;
}

.lx-footer-col { display: flex; flex-direction: column; }

.lx-footer-links { display: flex; flex-direction: column; gap: var(--s-2); }

/* Thirteen links down one line dictated the height of the whole footer. Two
   columns, filled top-to-bottom, roughly halve it without losing a link. */
.lx-footer-links--split {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(7, auto);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--s-5);
  row-gap: var(--s-2);
  align-content: start;
}

.lx-footer-col h2 {
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 var(--s-2);
  font-weight: 500;
}

.lx-footer-col a {
  font-size: var(--t-small);
  color: var(--ink-2);
  text-decoration: none;
}

.lx-footer-col a:hover { color: var(--ink); }

/* Touch sizing, and ONLY on a touch device.
   Measured at 390px: a footer link was 22.9px tall with an 8px gap, and the
   ship-to select 30.3px — both under the 44px floor --tap sets, and the
   links under WCAG 2.2's 24px minimum as well. Desktop geometry is
   deliberately untouched: padding on 30-odd links at pointer:fine would put
   back the footer height that 91d7b46 took out. */
@media (pointer: coarse) {
  .lx-footer-col a { padding-block: 4px; }
  .lx-shipto-select { min-height: var(--tap); }
}

.lx-footer-legal {
  border-top: 1px solid var(--line-strong);
  padding-block: var(--s-4);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-3);
}

.lx-footer-legal p { font-size: var(--t-meta); color: var(--ink-4); margin: 0; }

/* ==========================================================================
   LISTING, BREADCRUMBS, BUY CONTROLS, MODAL
   ========================================================================== */

.lx-breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  padding-block: var(--s-5) 0;
  font-size: var(--t-meta);
  color: var(--ink-3);
}

/* A breadcrumb link is 12.5px type, so its box is ~21px tall — under WCAG
   2.2 SC 2.5.8's 24px on a phone, where it is also the easiest way back. The
   height is claimed on a touch device only; the crumb row's own baseline is
   unchanged because align-items already centres it. */
.lx-breadcrumbs a { color: var(--ink-3); text-decoration: none; }
@media (pointer: coarse) {
  .lx-breadcrumbs a { display: inline-flex; align-items: center; min-height: 24px; }
}
.lx-breadcrumbs a:hover { color: var(--ink); text-decoration: underline; }
.lx-breadcrumbs [aria-current='page'] { color: var(--ink-2); }
.lx-crumb-sep { color: var(--line-strong); }

/* A listing opens like a chapter: air, then the name of the thing, then a line
   of context, then the goods. */
.lx-listing-head { padding-block: var(--s-8) var(--s-7); max-width: 62ch; }

.lx-listing-title {
  font-family: var(--serif);
  font-size: clamp(34px, 5vw, 60px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

.lx-listing-lede {
  font-size: var(--t-lede);
  line-height: 1.55;
  color: var(--ink-2);
  margin: var(--s-5) 0 0;
  max-width: 56ch;
}

.lx-listing-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4) var(--s-6);
  padding-block: var(--s-4);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.lx-filters {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  gap: var(--s-2);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  padding-block: 2px;
}

.lx-filters::-webkit-scrollbar { display: none; }

/* Filters are a line of words, not a row of buttons. Each is a tracked label
   with room around it; the selected one is inked and underlined. Twelve pill
   outlines above a grid of merchandise is the single most "marketplace" thing a
   luxury listing can do. */
.lx-chip {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--ctl-h-sm);
  padding-inline: 2px;
  margin-inline-end: var(--s-5);
  border: 0;
  border-bottom: 1px solid transparent;
  border-radius: 0;
  background: transparent;
  color: var(--ink-3);
  font: inherit;
  font-family: var(--sans);
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}

.lx-chip:last-child { margin-inline-end: 0; }
.lx-chip:hover { color: var(--ink); border-bottom-color: var(--champagne); }

.lx-chip[aria-pressed='true'] {
  background: transparent;
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.lx-chip:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

.lx-sort select {
  appearance: none;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  min-height: var(--ctl-h-sm);
  padding: 0 26px 0 2px;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%),
                    linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
  background-position: right 9px center, right 4px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.lx-sort select:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

.lx-listing-tools { display: flex; align-items: center; gap: var(--s-6); flex: none; }

/* ---- refinements --------------------------------------------------------
   Brand, price, size, colour and availability. The panel is only rendered when
   the catalogue can actually fill more than one of them — a filter drawer that
   opens onto a single disabled control is furniture. */
.lx-refine {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: repeat(1, minmax(0, 1fr));
  padding: var(--s-6);
  margin-bottom: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
}

.lx-refine[hidden] { display: none; }

@media (min-width: 720px)  { .lx-refine { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .lx-refine { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.lx-refine-group { border: 0; padding: 0; margin: 0; min-width: 0; }

.lx-refine-group legend {
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 0;
  margin-bottom: var(--s-3);
}

/* A long brand list scrolls inside its own column rather than making the whole
   panel taller than the products it is filtering. */
.lx-refine-group { max-height: 260px; overflow-y: auto; }

.lx-refine-option {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--t-small);
  color: var(--ink-2);
  min-height: 34px;
  cursor: pointer;
}

.lx-refine-option input { width: 17px; height: 17px; accent-color: var(--ink); flex: none; }
.lx-refine-option:hover { color: var(--ink); }

.lx-refine-price { display: flex; gap: var(--s-3); }
.lx-refine-price-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.lx-refine-price-field span { font-size: var(--t-meta); color: var(--ink-3); }

.lx-refine-price-field input {
  width: 100%;
  min-height: var(--ctl-h-sm);
  padding: 0 var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-small);
}

.lx-refine-price-field input:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }

.lx-refine-clear { grid-column: 1 / -1; justify-self: start; }

/* A button that reads as a link inside running text — used for "clear them
   all" inside an empty-state sentence. */
.lx-linkish {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--gold);
  text-decoration: underline;
  cursor: pointer;
}

.lx-listing-count {
  font-size: var(--t-meta);
  color: var(--ink-3);
  margin: var(--s-4) 0 var(--s-5);
}

.lx-listing-more { display: flex; justify-content: center; padding-block: var(--s-8); }

/* ---- buy controls ------------------------------------------------------- */

.lx-buy-row { display: flex; gap: var(--s-3); align-items: stretch; margin-bottom: var(--s-3); }
.lx-buy-row .lx-qty { flex: none; border-radius: var(--r-sm); }
.lx-buy-row .lx-qty button { width: 40px; height: 100%; min-height: var(--ctl-h); }

.lx-buy-feedback { font-size: var(--t-small); color: var(--ink-2); min-height: 20px; margin: var(--s-3) 0 var(--s-4); }
.lx-buy-feedback a { color: var(--gold); }

/* Save is not a second offer. It reads as a tracked label under the buy
   action rather than as a second full-width box competing with it. */
.lx-save-btn {
  margin-top: var(--s-4);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  border-radius: 0;
  color: var(--ink-2);
  min-height: 0;
  padding: var(--s-3) 0;
  width: auto;
  align-self: flex-start;
}

.lx-save-btn:hover { background: transparent; color: var(--ink); border-bottom-color: var(--ink); }
.lx-save-btn[aria-pressed='true'] { border-bottom-color: var(--ink); color: var(--ink); }

/* A sample listing says so where the buy decision is made, not only in the page
   banner. The buy button is disabled alongside it: the database would refuse
   the cart anyway, and a button that fails on click explains nothing. */
.lx-sample-notice {
  padding: var(--s-4);
  margin: 0 0 var(--s-4);
  border: 1px solid var(--champagne);
  border-radius: var(--r-sm);
  background: var(--gold-wash);
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--ink-2);
}

.lx-sample-notice b { color: var(--ink); font-weight: 500; }
.lx-sample-notice[hidden] { display: none; }

/* Eyewear states what is in the box in a sentence, above the spec table. */
.lx-spec-note {
  padding: var(--s-3) var(--s-4);
  margin: 0 0 var(--s-4);
  border-left: 2px solid var(--champagne);
  background: var(--ivory);
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--ink-2);
}

.lx-spec-note b { color: var(--ink); font-weight: 500; }

.lx-delivery-note { color: var(--ink-3); font-size: var(--t-meta); }

.lx-option-label { align-items: center; }

/* ---- sticky mobile buy bar ---------------------------------------------- */

.lx-stickybuy {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 45;
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3) var(--gutter);
  padding-bottom: calc(var(--s-3) + env(safe-area-inset-bottom, 0px));
  background: var(--paper);
  border-top: 1px solid var(--line);
  box-shadow: 0 -8px 24px -18px rgba(26, 22, 17, 0.4);
}

.lx-stickybuy[hidden] { display: none; }
.lx-stickybuy-info { display: flex; flex-direction: column; min-width: 0; flex: 1; }

.lx-stickybuy-title {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.lx-stickybuy-price { font-size: var(--t-meta); color: var(--ink-2); }
.lx-stickybuy .lx-btn { flex: none; }

/* The desktop layout keeps the buy column in view already, so the bar is a
   phone/tablet affordance only. */
@media (min-width: 900px) { .lx-stickybuy { display: none !important; } }

/* ---- modal (size guide) -------------------------------------------------- */

.lx-modal {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: var(--overlay);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: var(--s-4);
}

@media (min-width: 720px) { .lx-modal { align-items: center; } }

.lx-modal-panel {
  background: var(--paper);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  width: min(100%, 620px);
  max-height: 82vh;
  overflow-y: auto;
  box-shadow: var(--shadow-pop);
}

.lx-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s-4); }
.lx-modal-head h2 { font-family: var(--serif); font-size: var(--t-title-lg); font-weight: 500; margin: 0; color: var(--ink); }
.lx-modal-note { font-size: var(--t-small); color: var(--ink-2); margin: var(--s-4) 0 0; }

.lx-table-scroll { overflow-x: auto; }
.lx-table { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.lx-table th, .lx-table td { text-align: left; padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); white-space: nowrap; }
.lx-table th { color: var(--ink-3); font-weight: 500; font-size: var(--t-meta); letter-spacing: var(--track-label); }

/* ==========================================================================
   BAG DETAIL, CHECKOUT, ORDER
   ========================================================================== */

.lx-summary-title {
  font-family: var(--serif);
  font-size: var(--t-title);
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 var(--s-4);
}

.lx-bag-controls { display: flex; align-items: center; gap: var(--s-2); }
.lx-bag-money { text-align: right; font-size: var(--t-small); color: var(--ink); display: grid; gap: 2px; }
.lx-bag-unit { font-size: var(--t-meta); color: var(--ink-3); }
.lx-bag-title a { color: inherit; text-decoration: none; }
.lx-bag-title a:hover { text-decoration: underline; }
.lx-bag-unavailable { font-size: var(--t-meta); color: var(--danger); margin: 0 0 var(--s-2); }
.lx-bag-line.is-busy { opacity: .55; pointer-events: none; }
.lx-bag-continue { margin-top: var(--s-6); font-size: var(--t-small); }
.lx-bag-continue a { color: var(--gold); }

.lx-summary-unavailable { font-size: var(--t-small); color: var(--ink-3); margin: 0 0 var(--s-4); }
.lx-problem-detail { color: var(--ink-2); white-space: nowrap; }

.lx-checkout-btn { margin-top: var(--s-5); }
.lx-checkout-btn.is-disabled {
  background: var(--disabled-bg);
  color: var(--disabled-ink);
  pointer-events: none;
}

/* ---- checkout ----------------------------------------------------------- */

/* Checkout keeps its own reduced bar: the wordmark, and one way back to the
   bag. Same geometry as the utility bar everywhere else. */
.lx-header--checkout { position: static; border-bottom: 1px solid var(--line); }

.lx-header--checkout .lx-header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 56px;
}
.lx-checkout-back { font-size: var(--t-small); color: var(--ink-2); text-decoration: none; }
.lx-checkout-back:hover { color: var(--ink); text-decoration: underline; }

.lx-field-hint { font-size: var(--t-meta); color: var(--ink-3); margin: var(--s-1) 0 0; }
.lx-optional { color: var(--ink-4); text-transform: none; letter-spacing: 0; }

.lx-checkbox {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--t-small);
  color: var(--ink-2);
  margin-bottom: var(--s-4);
  cursor: pointer;
  min-height: var(--tap);
}

.lx-checkbox input { width: 18px; height: 18px; accent-color: var(--ink); flex: none; }

.lx-payment-heading {
  font-family: var(--serif);
  font-size: var(--t-title);
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 var(--s-4);
}

.lx-summary-line {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: var(--s-3);
  align-items: center;
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--t-small);
}

.lx-summary-line-thumb {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-xs);
  /* No overflow:hidden here — it cut the qty badge in half. The image clips
     itself with the same radius instead, so the badge can sit on the corner
     whole. */
  background: var(--ivory);
}

.lx-summary-line-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: var(--r-xs); }

.lx-summary-line-qty {
  position: absolute;
  top: -6px; right: -6px;
  min-width: 19px; height: 19px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--on-dark);
  font-size: 11px; line-height: 19px; text-align: center;
}

.lx-summary-line-body { display: grid; gap: 2px; min-width: 0; }
.lx-summary-line-title { color: var(--ink); }
.lx-summary-line-variant { font-size: var(--t-meta); color: var(--ink-3); }

/* ---- order -------------------------------------------------------------- */

.lx-order { display: grid; gap: var(--s-7); padding-bottom: var(--section-y); }

@media (min-width: 900px) {
  .lx-order { grid-template-columns: minmax(0, 1.4fr) minmax(300px, 0.6fr); gap: clamp(32px, 5vw, 64px); align-items: start; }
}

.lx-order-block { margin-bottom: var(--s-8); }

.lx-order-block-title {
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 var(--s-4);
  font-weight: 500;
}

.lx-order-item {
  display: grid;
  grid-template-columns: 72px 1fr auto;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--line);
  align-items: start;
}

.lx-order-side address { font-style: normal; font-size: var(--t-small); line-height: 1.7; color: var(--ink-2); }
.lx-order-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.lx-order-action-note { font-size: var(--t-small); color: var(--ink-2); margin: var(--s-3) 0 0; }

.lx-tracking { margin-top: var(--s-5); display: grid; gap: var(--s-3); }

.lx-tracking-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
  font-size: var(--t-small);
}

.lx-tracking-carrier, .lx-tracking-number { display: block; font-size: var(--t-meta); color: var(--ink-3); }
.lx-tracking-number { font-family: var(--mono); }

.lx-lookup { max-width: 460px; }
.lx-lookup-lede { font-size: var(--t-small); color: var(--ink-2); margin: var(--s-3) 0 var(--s-6); }
.lx-lookup .lx-fields { grid-template-columns: 1fr; }

.lx-return-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--s-3);
  align-items: center;
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-small);
}

.lx-return-item input[type='checkbox'] { width: 18px; height: 18px; accent-color: var(--ink); }
.lx-return-item select { min-height: 34px; border: 1px solid var(--line-strong); border-radius: var(--r-xs); background: var(--paper); font: inherit; font-size: var(--t-small); padding-inline: var(--s-2); }

/* ==========================================================================
   ACCOUNT, SEARCH BAR
   ========================================================================== */

.lx-searchbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-5);
  max-width: 620px;
}

.lx-searchbar input {
  flex: 1;
  /* A text input's implicit min-width is its size attribute, not 0, so at
     390px the row was 6px wider than the viewport and clipped the button.
     min-width:0 lets the input shrink; the wrap above is the fallback if the
     button alone ever outgrows the bar. */
  min-width: 0;
  min-height: var(--ctl-h);
  padding: 10px var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-body-app);
}

.lx-searchbar input:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; border-color: var(--gold); }

.lx-account { display: grid; gap: var(--s-7); padding-bottom: var(--section-y); }

@media (min-width: 900px) {
  .lx-account { grid-template-columns: 200px minmax(0, 1fr); gap: clamp(32px, 5vw, 64px); align-items: start; }
  .lx-account-nav { position: sticky; top: 96px; flex-direction: column; }
}

.lx-account-nav {
  display: flex;
  gap: var(--s-4);
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--s-3);
}

.lx-account-nav::-webkit-scrollbar { display: none; }

.lx-account-nav a {
  font-size: var(--t-small);
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  padding-block: var(--s-1);
}

.lx-account-nav a:hover { color: var(--ink); }
.lx-account-nav a.is-current { color: var(--ink); font-weight: 500; }

@media (min-width: 900px) {
  .lx-account-nav { border-bottom: 0; border-left: 1px solid var(--line); padding: 0 0 0 var(--s-4); }
  .lx-account-nav a { padding-block: var(--s-2); }
}

/* ---- account: resolving -------------------------------------------------
   A short placeholder shaped like the page that is coming, not the word
   "Loading…" over an empty screen. */
.lx-account-resolving {
  display: grid;
  gap: var(--s-4);
  padding-block: var(--s-8);
  max-width: 620px;
}

/* ---- account: signed out ------------------------------------------------
   Compact and complete: what an account is for, the two ways in, and the way
   to reach an order without one. Nothing private is rendered behind it. */
.lx-signedin-panel {
  max-width: 620px;
  padding: clamp(28px, 5vw, 48px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
}

.lx-signedin-panel .lx-listing-title { font-size: var(--t-h3); margin-top: var(--s-3); }

.lx-signedout-lede {
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink-2);
  margin: var(--s-4) 0 0;
}

.lx-signedout-guest {
  margin-top: var(--s-8);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}

.lx-signedout-guest h2 {
  font-family: var(--serif);
  font-size: var(--t-title-sm);
  font-weight: 500;
  color: var(--ink);
  margin: 0 0 var(--s-2);
}

.lx-signedout-guest p {
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0 0 var(--s-4);
  max-width: 48ch;
}

/* ---- account: signed out (redesigned) -----------------------------------
   The old state was a 620px panel stranded top-left of an empty viewport. It
   now composes like a storefront page: the case for an account on the left,
   the house photograph on the right, the guest path clearly separate. */
.lx-signedout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}

@media (min-width: 980px) {
  .lx-signedout { grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); }
}

.lx-signedout-copy { max-width: 52ch; }

.lx-signedout-media { margin: 0; }
.lx-signedout-media img {
  width: 100%; height: 100%; min-height: 420px; object-fit: cover;
  box-shadow: inset 0 0 0 1px var(--line);
}
@media (max-width: 979px) { .lx-signedout-media { display: none; } }

.lx-signedout-points {
  list-style: none;
  margin: var(--s-6) 0 var(--s-7);
  padding: 0;
  display: grid;
  gap: var(--s-4);
}

.lx-signedout-points li {
  display: grid;
  gap: 2px;
  padding: var(--s-4) 0;
  border-top: 1px solid var(--line);
}

.lx-signedout-points li:last-child { border-bottom: 1px solid var(--line); }
.lx-signedout-points b { font-size: var(--t-small); font-weight: 500; color: var(--ink); }
.lx-signedout-points span { font-size: var(--t-small); color: var(--ink-2); line-height: 1.55; }

/* ---- account: overview --------------------------------------------------
   The answer to "where is my order" before any tap. */
.lx-overview-latest {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
  text-decoration: none;
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease);
}

.lx-overview-latest:hover { border-color: var(--line-strong); }

.lx-overview-latest--empty { align-items: flex-start; gap: var(--s-3); }
.lx-overview-latest--empty .lx-btn { margin-top: var(--s-2); }

.lx-overview-latest-label {
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-3);
}

.lx-overview-latest-status {
  font-family: var(--serif);
  font-size: clamp(22px, 3vw, 28px);
  font-weight: 500;
  color: var(--ink);
}

.lx-overview-latest-meta { font-size: var(--t-small); color: var(--ink-2); }

.lx-overview-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-3);
  margin-top: var(--s-4);
}

.lx-overview-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r);
  text-decoration: none;
  color: var(--ink);
  min-height: var(--tap);
}

.lx-overview-stat:hover { border-color: var(--line-strong); }
.lx-overview-stat b { font-family: var(--serif); font-size: 26px; font-weight: 500; }
.lx-overview-stat span { font-size: var(--t-meta); color: var(--ink-3); }

/* ---- account: saved ----------------------------------------------------- */
.lx-saved-item { display: flex; flex-direction: column; gap: var(--s-2); }
.lx-saved-item.is-unavailable .lx-card-media { opacity: .5; }

.lx-card-unavailable {
  font-size: var(--t-meta);
  color: var(--ink-3);
  line-height: 1.4;
  margin-top: 2px;
}

/* ---- account: security --------------------------------------------------
   Kept apart from everything else so a destructive action is never one
   mis-tap away from an address edit. */
.lx-security-rows { display: grid; gap: var(--s-3); }

.lx-security-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r);
}

.lx-security-row b { display: block; font-size: var(--t-small); font-weight: 500; color: var(--ink); }
.lx-security-row span { display: block; font-size: var(--t-meta); color: var(--ink-2); max-width: 52ch; margin-top: 2px; }
.lx-security-row a { color: var(--gold); }
.lx-security-row--danger { border-color: var(--danger-wash); background: var(--danger-wash); }
.lx-security-row--danger .lx-btn { border-color: var(--danger); color: var(--danger); }

.lx-order-card {
  display: block;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
  text-decoration: none;
  color: inherit;
  margin-bottom: var(--s-4);
  transition: border-color var(--dur-fast) var(--ease);
}

.lx-order-card:hover { border-color: var(--line-strong); }

.lx-order-card-head {
  display: flex; justify-content: space-between; align-items: center; gap: var(--s-3);
  margin-bottom: var(--s-4);
}

.lx-order-card-number { font-family: var(--mono); font-size: var(--t-small); color: var(--ink); }

.lx-order-card-status {
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  padding: 3px 10px;
}

.lx-order-card-thumbs { display: flex; gap: var(--s-2); margin-bottom: var(--s-4); }

.lx-order-thumb {
  width: 52px; aspect-ratio: 4 / 5;
  border-radius: var(--r-xs);
  overflow: hidden;
  background: var(--ivory);
  flex: none;
}

.lx-order-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.lx-order-card-foot {
  display: flex; justify-content: space-between; gap: var(--s-3);
  font-size: var(--t-small); color: var(--ink-2);
}

.lx-address-card {
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s-5);
  margin-bottom: var(--s-3);
  background: var(--paper);
}

.lx-address-card address { font-style: normal; font-size: var(--t-small); line-height: 1.7; color: var(--ink); }
.lx-address-badges { display: flex; gap: var(--s-2); margin: var(--s-3) 0; flex-wrap: wrap; }

.lx-badge {
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--gold);
  background: var(--gold-wash);
  border-radius: var(--r-pill);
  padding: 3px 10px;
}

.lx-account-note { font-size: var(--t-small); color: var(--ink-3); margin: 0 0 var(--s-4); }
.lx-account-danger { margin-top: var(--s-8); font-size: var(--t-small); }
.lx-account-danger a { color: var(--danger); }

/* ---- long-form policy pages --------------------------------------------- */

/* Policy, help and About are set as a book page: one measured column, a large
   serif title on a hairline, and the same type scale as the rest of the site so
   a legal page never feels like a different website. */
.lx-prose {
  max-width: var(--maxw-prose);
  padding-block: clamp(40px, 5vw, 72px) var(--section-y);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--ink-2);
}

.lx-prose h1 {
  font-family: var(--serif);
  font-size: clamp(34px, 5vw, 60px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0 0 var(--s-7);
  padding-bottom: var(--s-6);
  border-bottom: 1px solid var(--line);
  text-wrap: balance;
}

.lx-prose h2 {
  font-family: var(--serif);
  font-size: clamp(21px, 2vw, 26px);
  font-weight: 400;
  color: var(--ink);
  margin: var(--s-9) 0 var(--s-4);
  text-wrap: balance;
}

.lx-prose h3 {
  font-family: var(--sans);
  font-size: var(--t-body);
  font-weight: 500;
  color: var(--ink);
  margin: var(--s-6) 0 var(--s-2);
}

.lx-prose p, .lx-prose li { margin: 0 0 var(--s-4); }
.lx-prose ol, .lx-prose ul { padding-left: 1.3em; margin: 0 0 var(--s-4); }
/* `.lx-prose a` is (0,1,1) and `.lx-btn--primary` is (0,1,0), so the prose
   link colour used to repaint the buttons at the foot of /about: measured
   live, "Browse the shop" rendered #7E6832 on #1A1611 — 3.35:1, under the
   4.5:1 AA floor for 12px text — and the ghost button lost its inverted
   hover the same way. check-contrast.mjs compares tokens against surfaces,
   so it cannot see a failure the cascade creates. */
.lx-prose a:not(.lx-btn) { color: var(--gold); }
.lx-prose a:not(.lx-btn):hover { color: var(--gold-deep); }
.lx-prose strong { color: var(--ink); font-weight: 500; }

.lx-prose-updated {
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
  margin: calc(var(--s-7) * -1) 0 var(--s-8);
  text-wrap: pretty;
}

/* A definition list of facts — seller identity, delivery windows — reads as a
   table rather than as running prose, because that is how it is used. */
.lx-prose dl {
  display: grid;
  gap: var(--s-2) var(--s-5);
  margin: 0 0 var(--s-5);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
}

@media (min-width: 640px) { .lx-prose dl { grid-template-columns: minmax(160px, auto) 1fr; } }

.lx-prose dt { color: var(--ink-3); font-size: var(--t-small); }
.lx-prose dd { margin: 0; color: var(--ink); font-size: var(--t-small); }

/* Something the reader must not skim past — a statutory right, or a limit on
   what we are claiming. */
.lx-prose-callout {
  padding: var(--s-5);
  margin: 0 0 var(--s-5);
  border-left: 2px solid var(--champagne);
  background: var(--ivory);
  font-size: var(--t-small);
  line-height: 1.6;
}

/* Static sub-category links on a generated category page. They are anchors,
   not buttons, so they are crawlable and open in place. */
.lx-filters--static { margin-bottom: var(--s-5); }
.lx-filters--static .lx-chip { text-decoration: none; display: inline-flex; align-items: center; }

/* The search page's starting point: rendered into the results grid under the
   empty and no-results states, so it spans the grid and wraps rather than
   scrolling — every category should be visible without a hint that there is
   more off-screen. */
.lx-search-cats {
  grid-column: 1 / -1;
  flex-wrap: wrap;
  justify-content: center;
  overflow: visible;
  padding-block: var(--s-4);
}

/* ---- announcement bar ----------------------------------------------------
   Three facts above the header. Two of them are written in by shop.js once the
   delivery market is known, because "prices include VAT" and "14 days to
   change your mind" are each true in exactly one of the two markets this shop
   sells into. Slots start hidden; see shop-chrome.js for why. */

.lx-announce {
  background: var(--obsidian);
  color: var(--on-dark);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}

.lx-announce-inner {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--s-6);
  min-height: 34px;

  /* On a phone the three sit in a row the reader scrolls, rather than a
     carousel that moves on its own. Nothing is hidden, nothing animates, and
     there is no reduced-motion branch to get wrong. */
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.lx-announce-inner::-webkit-scrollbar { display: none; }

.lx-announce-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  padding: 9px 0;
  scroll-snap-align: center;
  color: inherit;
  text-decoration: none;
  opacity: 0.92;
  white-space: nowrap;
}

.lx-announce-item:hover { opacity: 1; text-decoration: underline; text-underline-offset: 3px; }
/* --gold is #7E6832 and this bar is --obsidian #14110B: 3.2:1, which scrapes
   past SC 1.4.11's 3:1 for a focus indicator and does not look focused. The
   on-dark gold is the ring for a dark surface. */
.lx-announce-item:focus-visible { outline: 2px solid var(--gold-dark); outline-offset: -2px; }
.lx-announce-item svg { width: 15px; height: 15px; flex: 0 0 auto; opacity: 0.85; }

@media (max-width: 719px) {
  /* Edge padding so the first and last item are not flush against the screen
     edge mid-scroll. */
  .lx-announce-inner { justify-content: flex-start; gap: var(--s-5); padding-inline: var(--s-4); }
}

/* ---- ship-to flag --------------------------------------------------------
   Rendered only when the platform actually draws flag glyphs — Windows does
   not, and would show the bare letters "IT" beside the word Italy. shop.js
   measures once and omits this element entirely when it would not work. */
.lx-shipto-flag {
  font-size: 14px;
  line-height: 1;
  /* Keep the emoji off the text baseline metrics so it does not push the
     control's height around between platforms. */
  display: inline-block;
  transform: translateY(0.5px);
}

/* ---- card controls -------------------------------------------------------
   The save and quick-view controls are siblings of the card link, not children
   of it: a <button> inside an <a> is invalid, and browsers resolve it by
   following the link when the button was pressed. The wrapper owns the hover
   state for all three. */

.lx-card-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
}

/* The second gallery image, stacked exactly over the first and revealed on
   hover. Both are already in the layout, so the swap costs no reflow. */
.lx-card-media .lx-card-img--hover {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 420ms var(--ease);
}

.lx-card-wrap:hover .lx-card-media .lx-card-img--hover,
.lx-card-wrap:focus-within .lx-card-media .lx-card-img--hover { opacity: 1; }

/* An overlay box that mirrors the media exactly: inset-inline:0 gives it the
   card's width and aspect-ratio:4/5 gives it the media's height, so the
   controls inside can be positioned against the photograph's real edges
   without knowing how tall the title and price beneath it turned out. */
.lx-card-overlay {
  position: absolute;
  inset-inline: 0;
  top: 0;
  aspect-ratio: 4 / 5;
  z-index: 3;
  pointer-events: none;         /* the card link stays clickable through it */
}

.lx-card-overlay > * { pointer-events: auto; }

.lx-card-save {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  color: var(--ink-2);
  cursor: pointer;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.10);
  transition: color 200ms var(--ease), background 200ms var(--ease);
}

/* The visual mark stays 36px — a 44px plate would crowd the photograph — but
   36px is under the 44px floor --tap sets, so the hit area is extended
   invisibly to meet it. */
.lx-card-save::after { content: ''; position: absolute; inset: -4px; border-radius: 50%; }

.lx-card-save svg { width: 19px; height: 19px; }
.lx-card-save:hover { color: var(--ink); background: var(--paper); }
.lx-card-save:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Pressed state is carried by fill as well as colour, so it does not depend on
   distinguishing two similar hues. */
.lx-card-save.is-on { color: var(--gold); }
.lx-card-save.is-on svg { fill: currentColor; }

.lx-card-quick {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 8px;
  padding: 9px 12px;
  border: 0;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  color: var(--ink);
  font-size: var(--t-eyebrow);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 220ms var(--ease), transform 220ms var(--ease);
}

.lx-card-wrap:hover .lx-card-quick,
.lx-card-wrap:focus-within .lx-card-quick { opacity: 1; transform: translateY(0); }
.lx-card-quick:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; opacity: 1; transform: translateY(0); }

/* A touch screen has no hover, so a control that only appears on hover is a
   control that does not exist there. On coarse pointers quick view is always
   visible and the card is tall enough to carry it. */
@media (hover: none) {
  .lx-card-quick { opacity: 1; transform: none; }
  .lx-card-media .lx-card-img--hover { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .lx-card-media .lx-card-img--hover,
  .lx-card-quick { transition: none; }
}

/* ---- quick view ----------------------------------------------------------
   Enough to decide on, and a link to the page that holds everything else. */

.lx-noscroll { overflow: hidden; }

.lx-quick {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: var(--s-4);
}

.lx-quick[hidden] { display: none; }

.lx-quick-scrim {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--obsidian) 55%, transparent);
}

.lx-quick-panel {
  position: relative;
  z-index: 1;
  width: min(880px, 100%);
  max-height: min(88vh, 720px);
  overflow-y: auto;
  display: grid;
  grid-template-columns: 1fr;
  background: var(--paper);
  border-radius: var(--r-lg);
  box-shadow: 0 18px 60px rgb(0 0 0 / 0.22);
}

@media (min-width: 720px) {
  .lx-quick-panel { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
}

.lx-quick-body { display: contents; }

.lx-quick-x {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  color: var(--ink-2);
  cursor: pointer;
}

.lx-quick-x svg { width: 18px; height: 18px; }
.lx-quick-x:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.lx-quick-media {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--porcelain);
}

.lx-quick-media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.lx-quick-detail {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-6);
}

.lx-quick-loading {
  grid-column: 1 / -1;
  padding: var(--s-7) var(--s-6);
  text-align: center;
  color: var(--ink-3);
}

.lx-quick-brand {
  margin: 0;
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
}

.lx-quick-title { margin: 0; font-size: var(--t-title-sm); line-height: 1.25; }
.lx-quick-sub { margin: 0; color: var(--ink-2); }
.lx-quick-price { margin: 0; font-size: 18px; display: flex; gap: var(--s-3); align-items: baseline; }

.lx-quick-field { display: flex; flex-direction: column; gap: 6px; margin-top: var(--s-2); }

.lx-quick-field > span {
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-3);
}

.lx-quick-field select {
  font: inherit;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  min-height: 44px;
}

.lx-quick-field select:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.lx-quick-add { margin-top: var(--s-2); }
.lx-quick-feedback { margin: 0; min-height: 1.2em; font-size: var(--t-meta); color: var(--ink-2); }

.lx-quick-sample {
  margin: var(--s-2) 0 0;
  padding: var(--s-3) var(--s-4);
  border-left: 2px solid var(--gold);
  background: var(--ivory);
  color: var(--ink-2);
  font-size: var(--t-meta);
}

.lx-quick-full {
  margin-top: auto;
  padding-top: var(--s-3);
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
}

/* ---- checkout reassurance ------------------------------------------------
   Three short guarantees under the pay button, at the moment the decision is
   actually being made. Every one of them is something the Terms of Sale
   commit to — payment handled by Stripe and never stored here, every shipment
   tracked, and the EU statutory 14-day withdrawal period. */

.lx-reassure {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s-2) var(--s-4);
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  font-size: var(--t-meta);
  color: var(--ink-3);
}

.lx-reassure-item { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.lx-reassure-item svg { width: 15px; height: 15px; opacity: 0.8; }
