/* ==========================================================================
   mystore — storefront styles
   Luxury register: warm ivory paper, deep forest, champagne gold accents,
   square corners, generous whitespace. See PRD section 7.
   ========================================================================== */

:root {
  --paper: #f7f4ee;
  --card: #fffdf9;
  --ink: #191d1a;
  --deep: #173f31;
  --deep2: #0e2c22;
  --gold: #b3905e;
  --gold-soft: #efe6d6;
  --line: #e6e0d3;
  --muted: #7a776d;
  --danger: #a34632;

  --serif: "Cormorant Garamond", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --shell: 1180px;
  --gutter: clamp(16px, 4vw, 40px);
  --shadow: 0 18px 40px -28px rgba(23, 63, 49, 0.55);
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

/* The `hidden` attribute only sets `display: none` at UA-stylesheet priority, so
   any element that declares its own `display` (the hero grid, the login gate,
   the carousel dots) would keep showing. Make `hidden` mean hidden. */
[hidden] { display: none !important; }

a { color: inherit; }

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

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

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

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--deep);
  color: #fff;
  padding: 12px 18px;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
}
.skip-link:focus { left: 12px; top: 12px; }

/* --- Eyebrow / headings ------------------------------------------------- */

.eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0 0 10px;
}

.section-head {
  text-align: center;
  margin-bottom: clamp(24px, 4vw, 40px);
}

.section-head h1,
.section-head h2 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(28px, 4vw, 40px);
  line-height: 1.15;
  margin: 0;
  letter-spacing: 0.01em;
}

.rule {
  width: 46px;
  height: 1px;
  background: var(--gold);
  margin: 14px auto 0;
  border: 0;
}

/* --- Announcement bar --------------------------------------------------- */

.announce {
  background: var(--deep2);
  color: color-mix(in srgb, var(--on-deep) 84%, var(--gold));
  text-align: center;
  padding: 9px var(--gutter);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* --- Header ------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid var(--line);
}

.site-header .shell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* Deep enough for the logo and the store name to sit side by side. */
  min-height: clamp(78px, 8vw, 104px);
  /* Wraps when it has to rather than at one chosen width: with the wider brand,
     768px was too narrow for a single row but above the phone breakpoint, so the
     nav ran 8px off the side of the page. */
  flex-wrap: wrap;
  row-gap: 10px;
}

/* Lets the nav shrink instead of pushing past the edge. */
.site-header .nav { min-width: 0; }
.site-header .brand { min-width: 0; }

.brand {
  /* Logo first, wordmark beside it, both hanging off the left edge. */
  display: inline-flex;
  align-items: center;
  gap: clamp(10px, 1.4vw, 18px);
  text-decoration: none;
  color: var(--deep);
  white-space: nowrap;
}

/* The logo beside the wordmark. Capped, or an uploaded 400px square fills the
   header: these rules were lost when the wordmark block was rewritten, and the
   mark rendered at its natural size. */
.brand-logo {
  height: clamp(38px, 5vw, 58px);
  width: auto;
  max-width: min(200px, 34vw);
  object-fit: contain;
  flex: 0 0 auto;
}

/* The wordmark keeps to one line, except where a narrow phone needs it to wrap. */
.brand .brand-name { white-space: nowrap; }
@media (max-width: 420px) {
  .brand .brand-name { white-space: normal; line-height: 1.15; }

}

/* Anywhere else the name appears -- the footer's copyright line -- it is just
   words in a sentence and inherits the surrounding type. */
footer .brand-name,
.site-footer .brand-name {
  font: inherit;
  letter-spacing: inherit;
  text-transform: none;
  color: inherit;
  padding: 0;
  background: none;
  border: 0;
}

/*
 * The wordmark, driven entirely by settings.
 *
 * Every property here reads a custom property with a fallback, so the store
 * works untouched and the owner can change the face, weight, slant, case,
 * spacing, size, colour and what sits around it without a deploy. The colour
 * falls back to the theme's deep tone and is contrast-checked on save; the
 * accent falls back to the theme's gold and is only ever used for a rule or a
 * frame, never for the lettering.
 */
.brand .brand-name,
.brand > :not(.brand-logo) {
  position: relative;
  font-family: var(--brand-font, var(--serif));
  font-size: calc(clamp(25px, 3.4vw, 37px) * var(--brand-scale, 1));
  font-weight: var(--brand-weight, 600);
  font-style: var(--brand-style, normal);
  letter-spacing: var(--brand-tracking, 0.055em);
  text-transform: var(--brand-case, uppercase);
  line-height: 1.05;
  /* ink, not deep: deep is a dark brand tone and reads at 1.4:1 on a dark
     theme's paper. ink is the tone every theme guarantees against its page. */
  color: var(--brand-color, var(--ink));
}

/* Nothing around the name. */
.brand[data-brand-decoration="none"] .brand-name { padding: 0; }

/* A hairline under it, fading out. */
.brand[data-brand-decoration="underline"] .brand-name { padding-bottom: 7px; }
.brand[data-brand-decoration="underline"] .brand-name::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: linear-gradient(
    90deg,
    var(--brand-accent, var(--gold)) 0%,
    color-mix(in srgb, var(--brand-accent, var(--gold)) 25%, transparent) 100%
  );
}

/* A frame around it. */
.brand[data-brand-decoration="box"] .brand-name {
  padding: 0.28em 0.5em;
  border: 1px solid var(--brand-accent, var(--gold));
  border-radius: var(--brand-radius, 0);
}

/* A filled plate. The lettering flips to the theme's on-deep tone, which is the
   colour that is legible on a dark fill -- keeping the configured colour here
   would be the one combination guaranteed to disappear. */
.brand[data-brand-decoration="block"] .brand-name {
  padding: 0.28em 0.55em;
  background: var(--brand-accent, var(--deep));
  color: var(--brand-on-accent, var(--on-deep));
  border-radius: var(--brand-radius, 0);
}
/* Side room to match the corner shape, supplied as a value rather than derived
   from the radius: dividing the radius produced invalid CSS at 0 and an absurd
   185px at the pill's 999px. */
.brand[data-brand-decoration="block"] .brand-name,
.brand[data-brand-decoration="box"] .brand-name {
  padding-inline: var(--brand-pad-inline, 0.6em);
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(14px, 3vw, 30px);
}

.nav a,
.nav button {
  appearance: none;
  background: none;
  border: 0;
  padding: 6px 0;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  border-bottom: 1px solid transparent;
}
/* Words on a wide screen; the icon appears only where the words cannot fit. */
.nav-icon { display: none; }

.nav a:hover,
.nav button:hover,
.nav [aria-current="page"] { border-bottom-color: var(--gold); }

.search {
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--line);
  gap: 8px;
}
.search input {
  appearance: none;
  border: 0;
  background: transparent;
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 2px;
  width: clamp(110px, 18vw, 200px);
  color: var(--ink);
}
.search input:focus { outline: none; }
.search:focus-within { border-bottom-color: var(--gold); }
.search button {
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--muted);
  padding: 6px;
  line-height: 0;
}

/* Below ~760px the brand, search field and links cannot share one row.
   The search moves to a line of its own rather than overflowing the viewport. */
@media (max-width: 760px) {
  .site-header .shell {
    flex-wrap: wrap;
    row-gap: 8px;
    min-height: 0;
    padding-block: 10px;
  }

  /*
   * Three rows: the name with the links beside it, the search, the category
   * strip. The search is a child of .nav, not of the shell, so it wraps inside
   * the nav rather than being placed by the shell -- pinning the nav to its
   * content width instead forced a 345px block into 288px of space and pushed
   * the page sideways.
   */
  .brand { flex: 0 1 auto; min-width: 0; }

  /*
   * Two rows on a phone: the name, the search and a home icon, then the category
   * strip.
   *
   * The words "Home" and "Collection" are what cost a row here -- 42px of
   * overflow at 320px -- not the links themselves. So Home returns as an icon,
   * which is a 40px tap target rather than a line of text, and Collection stays
   * out because the strip already opens with "All". Most of this shop's visitors
   * are on a phone, and "how do I get back?" should not depend on knowing that
   * the shop's name is a link.
   */
  .site-header .nav > a[data-nav="collection"] { display: none; }

  .site-header .nav > a[data-nav="home"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* A finger's worth of target, not a text baseline. */
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    border-bottom: 0;
    flex: 0 0 auto;
    color: var(--ink);
  }
  .site-header .nav > a[data-nav="home"] .nav-icon { display: block; width: 22px; height: 22px; }
  .site-header .nav > a[data-nav="home"][aria-current="page"] { color: var(--accent-text); }

  /* The word stays for anything reading the page aloud. */
  .site-header .nav > a[data-nav="home"] .nav-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
  .site-header .nav {
    flex: 1 1 0;
    min-width: 0;
    justify-content: flex-end;
    gap: 12px;
  }
  .site-header .nav .search {
    order: 0;
    flex: 1 1 auto;
    min-width: 0;
  }
  .category-strip { padding-block: 9px; }

  .brand-name,
  .brand > :not(.brand-logo) { font-size: calc(21px * var(--brand-scale, 1)); }
  .brand[data-brand-decoration="underline"] .brand-name { padding-bottom: 5px; }

  .search input { width: 100%; flex: 1 1 auto; }
}

@media (max-width: 420px) {
  .brand .brand-name,
  .brand > :not(.brand-logo) { font-size: calc(18px * var(--brand-scale, 1)); }
  /*
   * The search and the home icon take a row of their own on the narrowest
   * phones.
   *
   * Sharing row one with the name left the search 28px wide at 320px -- a box
   * you cannot read your own typing in. Widening the search alone does not fix
   * it: the search sits inside .nav, so 100% means "all of the nav", and the nav
   * is only what the name left over. The whole nav has to take the row.
   *
   * It belongs in this block rather than the earlier 420px one, because the
   * 760px rules sit between them and reset the flex basis -- the first attempt
   * changed nothing for exactly that reason.
   */
  .site-header .nav { gap: 6px; flex: 1 1 100%; }
  .nav a { font-size: 10.5px; letter-spacing: 0.11em; }
}

/*
 * The bag icon on a narrow header.
 *
 * The same trap the home icon fell into: the button sits inside .nav beside the
 * search, so its width is taken straight out of the search box. At 320px the
 * word "Bag" plus its padding cost the search 24px and left it under the 180px
 * a person can read their own typing in. So below 760px the icon carries the
 * meaning and the word goes to screen readers only -- exactly what the home
 * icon does one rule above.
 */
@media (max-width: 760px) {
  /* Every pixel here comes straight out of the search box, which shares the row.
     A 22px icon with no padding is still a 40px+ tap target once the nav's own
     gap is counted, and the search stays readable. */
  .site-header .nav { gap: 8px; }
  .cart-button { padding: 4px 0; flex: 0 0 auto; }
  /* The gap and padding inside the search form are also width the input does
     not get. The magnifier is 16px; 6px of padding either side of it is room
     the box needs more. */
  .site-header .nav .search { gap: 4px; }
  .site-header .nav .search button { padding: 6px 2px; }
  .cart-button .nav-icon { display: block; width: 22px; height: 22px; }
  .cart-button .nav-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* --- Hero carousel ------------------------------------------------------ */

.hero {
  position: relative;
  /* The shape of the artwork the owner uploads: 1920x683, so a banner cut to
     spec fills the box exactly, with nothing cropped and no bands. Capped by
     viewport height so a tall, narrow window cannot hand the hero the whole
     screen and push the catalogue out of sight. */
  aspect-ratio: var(--hero-shape, 1920 / 683);
  max-height: 68vh;
  display: grid;
  isolation: isolate;
  background: linear-gradient(160deg, var(--deep) 0%, var(--deep2) 100%);
  overflow: hidden;
}

/* The slides live inside .hero-track, so the track has to be the grid that
   stacks them — otherwise they flow one below the other instead of crossfading. */
.hero-track {
  grid-area: 1 / 1;
  display: grid;
}

.hero-slide {
  grid-area: 1 / 1;
  position: relative;
  display: grid;
  place-items: center;
  /* The CTA and dots are absolutely positioned at the bottom of the hero, so the
     slide reserves room for them — otherwise long headlines collide with the
     button on narrow screens. */
  padding: clamp(28px, 6vh, 72px) var(--gutter) clamp(136px, 18vh, 164px);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 1.1s ease;
  pointer-events: none;
}
.hero-slide.is-active { opacity: 1; pointer-events: auto; }

/* "Show whole image": for artwork that carries its own text, which cropping
   would cut. Two layers -- a blurred zoomed copy filling the box, then the
   complete artwork centred on top of it -- so nothing is cropped and no bare
   letterbox bars appear whatever shape the upload is. */
.hero-fill,
.hero-art {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
}
.hero-fill {
  z-index: 0;
  background-size: cover;
  filter: blur(26px) saturate(1.15) brightness(0.72);
  /* Scaled up so the blur does not pull transparent edges into the box. */
  transform: scale(1.14);
}
.hero-art {
  z-index: 1;
  background-size: contain;
}
/*
 * The scrim, drawn only over a banner that carries words.
 *
 * Its whole purpose is contrast for the headline. A banner with no headline was
 * still being darkened by a third to a half -- dulling artwork the owner chose
 * and paid a photographer for, to make nothing readable. Every banner in this
 * shop is captionless today, so every one of them was being dimmed for nothing.
 */
.hero-slide.has-caption::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(rgba(14, 26, 20, 0.35), rgba(14, 26, 20, 0.55));
}

/* A far lighter scrim than a photographic banner gets: the artwork supplies its
   own contrast, and darkening it would dull the print. */
.hero-slide.is-fit.has-caption::before {
  z-index: 2;
  background: linear-gradient(rgba(14, 26, 20, 0.06), rgba(14, 26, 20, 0.22));
}

.hero-inner {
  position: relative;
  z-index: 3;
  text-align: center;
  color: var(--on-deep);
  max-width: 680px;
}

.hero-rule {
  width: 54px;
  height: 1px;
  background: var(--gold);
  margin: 0 auto 22px;
  border: 0;
}

.hero h1 {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(34px, 6.4vw, 62px);
  line-height: 1.08;
  margin: 0 0 16px;
  text-wrap: balance;
}

.hero p {
  margin: 0 auto 30px;
  max-width: 46ch;
  font-size: clamp(14px, 1.6vw, 17px);
  color: color-mix(in srgb, var(--on-deep) 86%, transparent);
  text-wrap: pretty;
}


.hero-dots {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: clamp(20px, 3vh, 30px);
  z-index: 3;
  display: flex;
  gap: 10px;
}

.hero-dots button {
  appearance: none;
  width: 9px;
  height: 9px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--on-deep) 75%, transparent);
  background: transparent;
  cursor: pointer;
}
.hero-dots button[aria-current="true"] { background: var(--gold); border-color: var(--gold); }

/* --- Buttons ------------------------------------------------------------ */

.btn {
  display: inline-block;
  appearance: none;
  border: 1px solid var(--deep);
  background: var(--deep);
  color: var(--on-deep);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 15px 34px;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.btn:hover { background: var(--deep2); border-color: var(--deep2); }

.btn-light {
  background: transparent;
  border-color: color-mix(in srgb, var(--on-deep) 70%, transparent);
  color: var(--on-deep);
}
.btn-light:hover { background: color-mix(in srgb, var(--on-deep) 12%, transparent); border-color: var(--on-deep); }

.btn-ghost {
  background: transparent;
  color: var(--deep);
}
.btn-ghost:hover { background: var(--deep); color: var(--on-deep); }

.btn[disabled] {
  cursor: not-allowed;
  opacity: 0.5;
  background: var(--muted);
  border-color: var(--muted);
}

.link-quiet {
  display: inline-block;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--deep);
  text-decoration: none;
  border-bottom: 1px solid var(--gold);
  padding-bottom: 3px;
}

.back-link {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}
.back-link:hover { color: var(--deep); }

/* --- Sections ----------------------------------------------------------- */

/* padding-block, not the shorthand: `padding: x 0` also set padding-inline to
   zero, which overrode the gutter .shell sets and ran every section — the
   collection grid, the product gallery — edge to edge on a phone. */
.section { padding-block: clamp(48px, 7vw, 86px); }
.section + .section { padding-block-start: 0; }
.section[hidden] { display: none; }

/* --- Category tiles ----------------------------------------------------- */

.category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: clamp(12px, 2vw, 22px);
}

.category-tile {
  position: relative;
  text-decoration: none;
  display: block;
  /* Square, because category art is square: a 4:5 portrait box cropped 20% off
     the width of every tile in the catalogue -- 10% from each side, straight
     through the piece the tile is meant to be showing. */
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border: 1px solid var(--line);
  background: linear-gradient(160deg, var(--deep) 0%, var(--deep2) 100%);
  cursor: pointer;
  padding: 0;
  text-align: left;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
/* The lift belongs to the tile; the shadow belongs to the art, which is round.
   On the square tile it drew a rectangular shadow around a circular image. */
.category-tile:hover { transform: translateY(-4px); }

.category-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Art that is not the tile's shape shows whole instead of being cropped, over a
   blurred copy of itself -- the tiles share one box so the grid stays even, and
   bare colour in the leftover space reads as a broken image. */
.category-tile.is-contained img {
  object-fit: contain;
  /* Positioned so it paints above the backdrop below. */
  position: relative;
}
.category-tile.is-contained::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--tile-art);
  background-size: cover;
  background-position: center;
  filter: blur(18px) brightness(0.68) saturate(1.1);
  transform: scale(1.16);
}

.category-tile::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  /* Above the artwork, below the label it exists to make readable. */
  z-index: 1;
  height: 62%;
  background: linear-gradient(rgba(14, 26, 20, 0), rgba(14, 26, 20, 0.72));
}

.category-tile span {
  position: absolute;
  z-index: 2;
  left: 0; right: 0; bottom: 18px;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 2.2vw, 23px);
  color: var(--on-deep);
  padding-inline: 10px;
}

/* A "show whole image" banner on a phone: the box is nearly square there
   (min-height wins over the width), so wide artwork floated in blurred bands —
   up to 129px above and below a 3:1 banner, two thirds of the box empty. On a
   phone the box takes the shape of the artwork instead, and the controls move
   below it, because 200px of height cannot hold an overlaid button as well. */
@media (max-width: 759px) {
  .hero,
  .hero.is-art {
    display: block;
    min-height: 0;
    max-height: none;
    aspect-ratio: auto;
  }
  .hero .hero-track { aspect-ratio: var(--hero-shape, 1920 / 683); }
  .hero.is-art .hero-track { aspect-ratio: var(--hero-ratio, 2); }
  .hero .hero-slide,
  .hero.is-art .hero-slide { padding: 0; }

  /* No scrim and no overlaid headline: artwork kept whole is artwork that
     carries its own words, so the overlay would print them twice. */
  .hero.is-art .hero-slide::before { display: none; }
  .hero.is-art .hero-inner { display: none; }

  .hero .hero-dots {
    position: static;
    transform: none;
    display: flex;
    justify-content: center;
  }
  .hero .hero-dots { padding: 14px 0 18px; }
  /* The artwork carries its own words at this size. */
  .hero .hero-inner { display: none; }
  .hero .hero-slide::before { display: none; }
}

/* --- Product grid & cards ----------------------------------------------- */

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: clamp(16px, 2.4vw, 30px);
}

/* A minimum column width means one column on every phone, which makes each tile
   as wide as the screen. Two columns of 180px plus the gap need 372px, but a
   390px phone only offers 358px inside the gutter, so the category grid
   collapsed to one 358px square per row while the products beside it sat
   two-up. Every tile grid is explicitly two-up on a phone. */
@media (max-width: 759px) {
  .category-grid,
  .product-grid,
  .skeleton-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
  }
}

.card {
  position: relative;
  text-decoration: none;
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--line);
  cursor: pointer;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: center;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }

/* A category card wears its photograph's own shape, so a row of them holds
   several heights. Grid items stretch to their row by default, which does not
   stretch the picture -- it hands the spare height to the card below the name,
   as a band of empty paper. Sized to its contents instead, each card ends where
   its label does. */
.card-category { align-self: start; }

.card-media {
  position: relative;
  /* Set per product, so a piece shot on a stand is not cropped square. */
  aspect-ratio: var(--media-ratio, 1 / 1);
  background: var(--gold-soft);
  overflow: hidden;
}
.card-media img { width: 100%; height: 100%; object-fit: cover; }

.card-media .placeholder {
  display: grid;
  place-items: center;
  width: 100%; height: 100%;
  font-size: 34px;
  color: var(--muted);
}

/*
 * A sold-out piece keeps its own colours.
 *
 * This used to be grayscale(1) at 55% opacity, which hid the one thing a shopper
 * is looking at -- a saree's colour -- and made the photo look broken rather
 * than unavailable. The "Sold out" mark says what the greying was trying to say,
 * and says it in words.
 */
.card.is-sold-out .card-media img { filter: none; opacity: 1; }

.tag {
  position: absolute;
  z-index: 2;
  top: 10px;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 9px;
  color: var(--on-deep);
}
.tag-promo { right: 10px; background: var(--deep); }
.tag-sold { left: 10px; background: var(--danger); }

.card-body { padding: 16px 14px 20px; }

.card-eyebrow {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0 0 7px;
}

.card-name {
  font-family: var(--serif);
  font-size: clamp(17px, 2vw, 21px);
  font-weight: 500;
  line-height: 1.25;
  margin: 0 0 8px;
}

.card-price {
  margin: 0;
  font-size: 13px;
  color: var(--muted);
  letter-spacing: 0.04em;
}

/* --- Prices -------------------------------------------------------------
   A sale shows three parts: what you pay, the former price struck through,
   and the saving. The current price carries the weight so the eye lands on it
   first; the former price recedes. */
.price-now { color: var(--ink); }
.price-now.is-sale { font-weight: 600; }

.price-was {
  margin-inline-start: 8px;
  color: var(--muted);
  /* The strike is the whole point of the element, so it is drawn deliberately
     rather than left to the browser's default weight. */
  text-decoration-thickness: 1px;
  text-decoration-color: var(--muted);
}

.price-off {
  margin-inline-start: 8px;
  font-size: 0.82em;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--danger);
}

/* --- Collection view ---------------------------------------------------- */

.chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-bottom: clamp(26px, 4vw, 42px);
}

.chip {
  appearance: none;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 9px 18px;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.chip:hover { border-color: var(--gold); }
.chip[aria-pressed="true"] { background: var(--deep); border-color: var(--deep); color: var(--on-deep); }

/* The back link and the title share one row. The two 1fr side columns are
   equal, so the title stays optically centred on the page while the link sits
   in the left one. */
.view-head {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 20px;
  margin-bottom: clamp(22px, 3vw, 34px);
}
.view-head .back-row {
  grid-column: 1;
  justify-self: start;
}
.view-head .section-head {
  grid-column: 2;
  margin-bottom: 0;
}

/* The collection and product views open straight into their content: no tall
   pad under the nav, and on the collection the rule tucked closer to the
   heading. */
#listView .section,
#detailView .section { padding-block-start: clamp(18px, 2vw, 26px); }
#listView .rule { margin-block-start: 8px; }
/* Flex, not a bare line box: the paragraph's strut would otherwise push the
   small back link a few pixels down and the two pages would open unevenly. */
#detailView .back-row {
  display: flex;
  margin: 0 0 16px;
}

/* Narrow screens: one row would crowd, so it stacks as before — back link
   above a centred title. */
@media (max-width: 620px) {
  .view-head {
    grid-template-columns: 1fr;
    row-gap: 12px;
  }
  .view-head .back-row,
  .view-head .section-head { grid-column: 1; }
}

.chip-child { font-size: 10px; padding: 8px 14px; }

/* --- More pieces, under a product --------------------------------------- */

/* A hairline and a generous gap: the row is a change of subject, not more of
   the product above it. */
.related {
  margin-block-start: clamp(52px, 8vw, 88px);
  padding-block-start: clamp(32px, 5vw, 56px);
  border-block-start: 1px solid var(--line);
}

/* --- Detail view -------------------------------------------------------- */

.detail {
  display: grid;
  gap: clamp(24px, 4vw, 54px);
  align-items: start;
}

/* On a phone the photo is a whole screenful, so with the name inside the text
   column it sat about 970px down the page — the product had no visible title
   until you scrolled past the image and its thumbnails. The name and price
   come first instead, then the photo, then the rest. */
.detail-head { order: -1; }
.detail-head .detail-name,
.detail-head .detail-price { margin-block-end: 0; }

@media (min-width: 760px) {
  .detail {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "media head"
      "media info";
    grid-template-rows: auto 1fr;
    column-gap: clamp(24px, 4vw, 54px);
    row-gap: 18px;
  }
  .detail-media { grid-area: media; }
  .detail-head { grid-area: head; }
  .detail-info { grid-area: info; }
}

.gallery-main {
  aspect-ratio: var(--media-ratio, 1 / 1);
  background: var(--gold-soft);
  border: 1px solid var(--line);
  overflow: hidden;
  position: relative;
  /* The browser keeps vertical scrolling; sideways movement is the gallery's,
     so a swipe through the photos does not fight the page. */
  touch-action: pan-y;
  /* A drag across the photo is a swipe, not a text or image selection. */
  user-select: none;
  -webkit-user-select: none;
}
.gallery-main img { width: 100%; height: 100%; object-fit: cover; }
.gallery-main .placeholder { display: grid; place-items: center; height: 100%; font-size: 54px; color: var(--muted); }
/* Same on the product page: the photo is the reason the page was opened. */
.gallery-main.is-sold-out img { filter: none; opacity: 1; }

.thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}
.thumbs button {
  width: 68px;
  height: auto;
  aspect-ratio: var(--media-ratio, 1 / 1);
  padding: 0;
  border: 1px solid var(--line);
  background: var(--gold-soft);
  cursor: pointer;
  overflow: hidden;
}
.thumbs button[aria-current="true"] { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.thumbs img { width: 100%; height: 100%; object-fit: cover; }

.detail-name {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(30px, 4.6vw, 48px);
  line-height: 1.1;
  margin: 0 0 14px;
}

.detail-price {
  font-size: 19px;
  letter-spacing: 0.05em;
  color: var(--ink);
  margin: 0 0 20px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
}
/* The spacing is carried by the margins on the parts themselves, so a card and
   the product page set the trio identically. */
.detail-price .price-was { font-size: 0.85em; }

.detail-desc {
  color: var(--ink);
  margin: 0 0 30px;
  max-width: 60ch;
}
.detail-desc p { margin: 0 0 14px; }
.detail-desc p:last-child { margin-bottom: 0; }
.detail-desc h3,
.detail-desc h4 {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 22px 0 8px;
}
.detail-desc ul,
.detail-desc ol { margin: 0 0 14px; padding-left: 20px; }
.detail-desc li { margin-bottom: 5px; }
.detail-desc blockquote {
  margin: 0 0 14px;
  padding-left: 14px;
  border-left: 1px solid var(--gold);
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
}
.detail-desc a { color: var(--accent-text); text-underline-offset: 3px; }
.detail-desc strong { font-weight: 600; }

/* Attribute list on the product page. */
.spec {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 18px;
  margin: 0 0 28px;
  font-size: 13px;
}
.spec dt {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  align-self: center;
}
.spec dd { margin: 0; color: var(--ink); }

.detail-meta {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.04em;
}
.detail-meta p { margin: 0 0 6px; }
.detail-sku { letter-spacing: 0.12em; text-transform: uppercase; font-size: 11px; }

.sold-note {
  color: var(--danger);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 0 0 16px;
}

.buy-slot { min-height: 52px; }
.buy-slot form { margin: 0; }

/* --- Variant options ---------------------------------------------------- */

.options { margin: 0 0 26px; display: grid; gap: 16px; }

.option-name {
  margin: 0 0 8px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}

.option-values { display: flex; flex-wrap: wrap; gap: 8px; }

.option-chip[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
  text-decoration: line-through;
}
.option-chip[disabled]:hover { border-color: var(--line); }

/* --- Email capture band ------------------------------------------------- */

.capture {
  background: linear-gradient(140deg, var(--deep) 0%, var(--deep2) 100%);
  color: var(--on-deep);
  padding: clamp(30px, 4vw, 52px) 0;
  margin-top: clamp(32px, 5vw, 60px);
  text-align: center;
}
.capture h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-style: italic;
  font-size: clamp(26px, 3.6vw, 38px);
  margin: 0 0 8px;
}
.capture p { margin: 0 auto 16px; max-width: 44ch; color: color-mix(in srgb, var(--on-deep) 80%, transparent); font-size: 14px; }
.capture .eyebrow { color: var(--gold); margin-bottom: 6px; }

.capture-form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  max-width: 520px;
  margin-inline: auto;
}
.capture-form input {
  flex: 1 1 240px;
  min-width: 0;
  appearance: none;
  border: 1px solid color-mix(in srgb, var(--on-deep) 40%, transparent);
  background: color-mix(in srgb, var(--on-deep) 6%, transparent);
  color: var(--on-deep);
  font-family: var(--sans);
  font-size: 14px;
  padding: 14px 16px;
}
.capture-form input::placeholder { color: color-mix(in srgb, var(--on-deep) 55%, transparent); }
.capture-form input:focus { outline: none; border-color: var(--gold); }

/* ---- signup popup: a small corner card, shown once after a few clicks ---- */
.signup-pop {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  width: min(340px, calc(100vw - 32px));
  background: var(--deep);
  color: var(--on-deep);
  border-radius: 14px;
  padding: 22px 22px 20px;
  box-shadow: 0 16px 48px rgba(14, 44, 34, 0.35);
  transform: translateY(16px);
  opacity: 0;
  transition: opacity 0.28s ease, transform 0.28s ease;
}
.signup-pop.is-open { opacity: 1; transform: translateY(0); }
.signup-pop[hidden] { display: none; }
.signup-close {
  position: absolute;
  top: 8px;
  right: 10px;
  appearance: none;
  border: 0;
  background: none;
  color: color-mix(in srgb, var(--on-deep) 70%, transparent);
  font-size: 24px;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
}
.signup-close:hover { color: var(--on-deep); }
.signup-eyebrow { margin: 0 0 4px; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold); }
.signup-title { margin: 0 0 8px; font-size: 18px; line-height: 1.2; color: var(--on-deep); }
.signup-text { margin: 0 0 14px; font-size: 13px; line-height: 1.5; color: color-mix(in srgb, var(--on-deep) 82%, transparent); }
.signup-form { display: grid; gap: 8px; }
.signup-form input {
  appearance: none;
  border: 1px solid color-mix(in srgb, var(--on-deep) 40%, transparent);
  background: color-mix(in srgb, var(--on-deep) 8%, transparent);
  color: var(--on-deep);
  font-family: var(--sans);
  font-size: 14px;
  padding: 11px 13px;
  border-radius: 8px;
}
.signup-form input::placeholder { color: color-mix(in srgb, var(--on-deep) 55%, transparent); }
.signup-form input:focus { outline: none; border-color: var(--gold); }
.signup-form .btn {
  margin-top: 2px;
  padding: 12px 18px;
  background: var(--gold);
  border-color: var(--gold);
  color: #16281f;
  letter-spacing: 0.14em;
}
.signup-form .btn:hover { background: var(--on-deep); border-color: var(--on-deep); color: var(--deep); }
.signup-msg { margin: 8px 0 0; font-size: 12px; min-height: 1em; }
.signup-msg.is-error { color: #f0c0b4; }
.signup-msg.is-ok { color: var(--gold); }
@media (max-width: 480px) {
  .signup-pop { right: 12px; left: 12px; bottom: 12px; width: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .signup-pop { transition: opacity 0.2s ease; transform: none; }
}

.capture-msg {
  margin: 14px 0 0;
  font-size: 13px;
  letter-spacing: 0.04em;
}
.capture-msg:empty { display: none; }
.capture-msg.is-error { color: #ffbcae; }
.capture-msg.is-ok { color: var(--gold-soft); }

/* --- Footer ------------------------------------------------------------- */

.site-footer {
  background: var(--paper);
  border-top: 1px solid var(--line);
  padding: 40px 0;
  font-size: 12px;
  color: var(--muted);
}
.site-footer .shell {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: space-between;
  align-items: center;
}
.site-footer a { color: var(--muted); text-decoration: none; letter-spacing: 0.16em; text-transform: uppercase; font-size: 11px; }
.site-footer a:hover { color: var(--deep); }

/* --- States ------------------------------------------------------------- */

.empty {
  text-align: center;
  color: var(--muted);
  padding: clamp(40px, 8vw, 90px) 0;
}
.empty h2 {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  color: var(--ink);
  font-size: clamp(24px, 3.4vw, 34px);
  margin: 0 0 12px;
}
.empty p { margin: 0 auto 18px; max-width: 44ch; }
/* The kicker belongs to the headline under it, not to the paragraph spacing. */
.empty .eyebrow { margin-bottom: 8px; color: var(--accent-text); }
.empty .btn { margin-top: 4px; }

.skeleton-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 24px; }
.skeleton {
  aspect-ratio: 3 / 4;
  background: linear-gradient(100deg, var(--gold-soft) 30%, #f6f1e7 50%, var(--gold-soft) 70%);
  background-size: 300% 100%;
  animation: shimmer 1.4s linear infinite;
}
@keyframes shimmer {
  from { background-position: 150% 0; }
  to { background-position: -50% 0; }
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 16px);
  z-index: 60;
  background: var(--deep2);
  color: var(--on-deep);
  padding: 13px 22px;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .hero-slide { transition: none; }
}

/* --- Share row ---------------------------------------------------------- */

.share {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 22px;
}

.share-label {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.share-btn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--deep);
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.share-btn:hover,
.share-btn:focus-visible {
  background: var(--deep);
  border-color: var(--deep);
  color: var(--on-deep);
}
.share-btn svg { width: 20px; height: 20px; display: block; }

/* --- Popular categories -------------------------------------------------- */

/* A row of the promoted categories, above the banner, so they are reachable
   without scrolling past it. Scrolls sideways on a phone rather than wrapping
   into a block that pushes the banner down the page. */
.category-strip {
  display: flex;
  gap: clamp(14px, 2vw, 30px);
  align-items: center;
  /*
   * `center` alone loses the first items when the row overflows: the overflow is
   * split both ways, so the start scrolls off to the left and cannot be reached.
   * On a phone that showed the strip already cut mid-word. `safe center` centres
   * only while everything fits and falls back to the start when it does not.
   */
  justify-content: flex-start;
  justify-content: safe center;
  padding: 12px var(--gutter);
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
}
.category-strip::-webkit-scrollbar { display: none; }

.category-strip a {
  flex: 0 0 auto;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  white-space: nowrap;
}
.category-strip a:hover,
.category-strip a:focus-visible { border-bottom-color: var(--gold); }

/* Round category art, with the name beneath it rather than across it: a circle
   would clip a label laid over the bottom of the tile. */
.category-tile {
  aspect-ratio: auto;
  border: 0;
  background: none;
  overflow: visible;
  display: grid;
  gap: 12px;
  justify-items: center;
  /* Rows sized to their content, not stretched to fill the tile. Tiles stretch
     to the tallest in the row, and the spare height was being handed to the art
     row -- which a photo ignores (its height comes from its ratio) but the
     placeholder took, so one circle rendered 215px beside 202px neighbours. */
  align-content: start;
  text-align: center;
}
.category-tile img,
.category-tile.is-contained img {
  aspect-ratio: 1 / 1;
  width: 100%;
  height: auto;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--line);
  background: var(--gold-soft);
}
.category-tile.is-contained::before { display: none; }
.category-tile::after { display: none; }
.category-tile span {
  position: static;
  inset: auto;
  color: var(--ink);
  font-size: clamp(13px, 1.5vw, 16px);
  letter-spacing: 0.04em;
  padding: 0;
}
.category-tile:hover img,
.category-tile:focus-visible img,
.category-tile:hover .tile-blank { box-shadow: var(--shadow); }

/* Holds the circle's place when a category has no photo yet. */
.tile-blank {
  width: 100%;
  aspect-ratio: 1 / 1;
  /* Belt to the align-content brace above: never taller than its own ratio. */
  align-self: start;
  border-radius: 50%;
  background: var(--gold-soft);
  border: 1px solid var(--line);
}

/* --- The rail under a product ------------------------------------------- */

/*
 * A sideways shelf rather than a grid: the row holds more pieces than fit, so
 * it scrolls. Touch scrolls it directly; the arrows are for a mouse, and they
 * hide themselves when there is nothing to scroll.
 */
.rail {
  position: relative;
}

.rail-track {
  display: flex;
  /*
   * Each card keeps its own height. Stretching is the flex default, and with
   * mixed photo shapes in one row it padded every square card with dead space:
   * measured on the home rail, one 3:4 card made six 1:1 cards 474px tall for
   * 342px of content.
   */
  align-items: start;
  gap: 16px;
  overflow-x: auto;
  scroll-behavior: smooth;
  scroll-snap-type: x proximity;
  /* Room for the cards' hover lift, which would otherwise be clipped. */
  padding: 6px 2px 10px;
  scrollbar-width: thin;
}

.rail-track > .card {
  flex: 0 0 clamp(150px, 42vw, 232px);
  scroll-snap-align: start;
}

.rail-arrow {
  position: absolute;
  top: calc(50% - 22px);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: opacity 0.2s ease, background 0.2s ease;
}
.rail-arrow svg { width: 20px; height: 20px; }
.rail-prev { left: -6px; }
.rail-next { right: -6px; }
.rail-arrow:hover { background: var(--gold-soft); }
.rail-arrow:disabled { opacity: 0.3; cursor: default; }

/* On a touch screen the finger is the control, so the arrows stay out of the
   way of the cards. */
@media (hover: none) {
  .rail-arrow { display: none; }
}

/*
 * The product's title, under its name.
 *
 * Smaller and lighter than the name: the name identifies the piece, the title
 * describes it, and running them together on one line made both harder to scan.
 */
.card-title {
  margin: 2px 0 0;
  font-size: 0.82em;
  line-height: 1.35;
  color: var(--muted);
  text-wrap: pretty;
}

/*
 * Which variant a card is for, following the name on the same line.
 *
 * Small enough that the name still leads, and in the quieter tone, so the pair
 * reads as one thing -- this piece, in this colourway -- rather than as two
 * competing lines. em-relative, so it tracks the name at every viewport.
 */
.card-variant {
  /*
   * Set like the category label at the top of the card: the page sans,
   * uppercase, letterspaced. It sits inside the name, which is serif, so the
   * family has to be stated -- inheriting is what made it read as small serif
   * caps rather than as a label.
   */
  font-family: var(--sans);
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  /*
   * Dark, without being the flat near-black the name is set in. Mixed from the
   * palette's own two ends rather than picked as a literal, so it follows every
   * theme: across all thirteen it lands at 11.3-12.5:1 against the card, where
   * ink itself is 14-17.8. The brand's deep tone was the obvious candidate and
   * is unusable -- on the two onyx themes it measures 1.32:1, a dark green on a
   * dark card.
   *
   * The plain declaration first is the fallback for anything without color-mix.
   */
  color: var(--muted);
  color: color-mix(in srgb, var(--ink) 88%, var(--card));
  /*
   * A label too wide for the card wraps inside itself rather than running out of
   * it; `anywhere` is the last resort for one word that still will not fit.
   * Forbidding the wrap outright (white-space: nowrap) kept the label whole but
   * pushed "Violet-Yellow Deluxe" straight out of a 360px card.
   */
  overflow-wrap: anywhere;
}

.card-variant::before {
  /*
   * A non-breaking hyphen (U+2011), not a plain one.
   *
   * The dash belongs to the label, not to the name, so it is drawn here rather
   * than written into the markup. A hyphen-minus is Unicode line-break class
   * HY, which permits a break right after it -- and rule LB12a exempts it from
   * the usual "no break before a non-breaking space" -- so even "-\00a0" split,
   * measured on a 360px card as the dash alone on one line (top 670) and the
   * colourway on the next (top 692). U+2011 is class GL: nothing breaks either
   * side of it, so the dash always travels with the label, and the space before
   * it in the markup stays the one place a break may fall. It draws the same
   * glyph.
   */
  content: "\2011\00a0";
  letter-spacing: normal;
}

.detail-title {
  margin: 6px 0 0;
  font-family: var(--serif);
  font-size: clamp(15px, 1.9vw, 20px);
  line-height: 1.3;
  color: var(--ink-soft, var(--muted));
  text-wrap: pretty;
}

/*
 * An option whose variants are all sold out.
 *
 * Struck through and quietened, but still a working control: choosing it is how
 * a shopper gets to the waiting list. Distinct from a disabled chip, which is a
 * combination that does not exist at all and cannot be chosen.
 */
.option-chip.is-sold-out {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  color: var(--muted);
  border-color: var(--line);
}
.option-chip.is-sold-out[aria-pressed="true"] {
  /* Still legible as the current choice, which is where the form appears. */
  color: var(--on-deep);
  text-decoration-color: color-mix(in srgb, var(--on-deep) 60%, transparent);
}

/*
 * The same offer on a card, for a piece that is sold out.
 *
 * Underlined and in the accent tone so it reads as the thing the card will do,
 * rather than as another line of description. It is text, not a control: the
 * card is already one link, and a button inside a link is invalid markup that no
 * keyboard can reach.
 */
.card-notify {
  margin: 6px 0 0;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.card:hover .card-notify { color: var(--deep); }

/* --- "Tell me when it's back" -------------------------------------------- */

/*
 * Shown under the disabled Sold out button, which would otherwise be the end of
 * the page for a shopper who wanted exactly this piece.
 */
.notify { margin-top: 14px; }

.notify-open {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.notify-open:hover { color: var(--deep); }

.notify-form {
  display: grid;
  gap: 10px;
  margin-top: 12px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  max-width: 340px;
}

.notify-what { margin: 0; font-size: 13px; color: var(--muted); }

.notify-field { display: grid; gap: 4px; }
.notify-field > span {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
/* The word "optional" belongs to the label, not to the emphasis of a heading. */
.notify-field em { font-style: normal; font-weight: 400; letter-spacing: 0.04em; text-transform: none; }

.notify-field input {
  font-family: var(--sans);
  font-size: 15px;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  color: var(--ink);
}
.notify-field input:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }

.notify-msg:empty { display: none; }
.notify-msg { margin: 0; font-size: 13px; color: var(--muted); }

.notify-done {
  margin: 0;
  font-size: 14px;
  color: color-mix(in srgb, var(--ink) 88%, var(--card));
}

/*
 * Footer separators, drawn rather than typed.
 *
 * They were literal "&nbsp;·&nbsp;" text nodes between the links, which only
 * looked right while every link was present: a shop with no Instagram set showed
 * "Collection ·" with a dot leading nowhere. Generated content belongs to the
 * link it precedes, so a hidden link takes its separator with it.
 */
.site-footer nav a + a::before {
  content: "·";
  margin: 0 8px;
  color: color-mix(in srgb, currentColor 55%, transparent);
}

/* --- Subcategory row ------------------------------------------------------ */

/*
 * The second filter row, and deliberately not a copy of the first.
 *
 * The rows answer different questions -- which part of the shop, then where
 * inside it -- so the second is smaller, rounded, and quieter, and sits closer
 * to the grid it is narrowing. They used to be one wrapped line distinguished
 * by a "└" glyph, which at chip size read as a stray character.
 */
.chips-sub {
  margin-top: -6px;
  padding-bottom: 4px;
}

.chip-sub {
  font-size: 10px;
  letter-spacing: 0.1em;
  padding: 6px 14px;
  border-radius: 999px;
  border-color: color-mix(in srgb, var(--line) 70%, transparent);
  background: transparent;
  color: var(--muted);
}
.chip-sub:hover { color: var(--ink); border-color: var(--gold); }
.chip-sub[aria-pressed="true"] {
  background: var(--gold-soft, color-mix(in srgb, var(--gold) 16%, transparent));
  border-color: var(--gold);
  color: var(--ink);
}

/* --- Growing the listing -------------------------------------------------- */

.list-more {
  display: grid;
  justify-items: center;
  gap: 10px;
  padding: 28px 0 4px;
}

.list-count {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* --- Like ----------------------------------------------------------------- */

/*
 * Beside the buy control, where a shopper has just weighed the piece up. Quiet
 * until pressed: it is an aside to buying, not a competing call to action.
 */
.like-slot { margin-top: 12px; }

.like-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 16px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  background: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.like-btn svg { width: 17px; height: 17px; }
.like-btn:hover { border-color: var(--gold); }
.like-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Liked reads as a state, not as a hover: filled heart, warmer tone, and the
   button keeps its size so the row does not shift under the finger. */
.like-btn.is-liked {
  color: var(--danger, #b4432f);
  border-color: color-mix(in srgb, var(--danger, #b4432f) 45%, transparent);
  background: color-mix(in srgb, var(--danger, #b4432f) 8%, transparent);
}

/* =========================================================================
   The bag
   =========================================================================
   A right-hand drawer on desktop, a full sheet on a phone. It sits above
   everything, so its own scroll container is what moves -- the page behind is
   frozen by .cart-open rather than left to scroll under the panel, which is
   the classic way a drawer loses the shopper's place.
   ========================================================================= */

.btn-quiet {
  background: transparent;
  color: var(--deep);
  border-color: var(--line);
}
.btn-quiet:hover { background: var(--gold-soft); border-color: var(--gold); color: var(--deep2); }

/* A highlighted secondary — a warm gold fill that draws the eye to the next
   step without ever matching the green primary beside it, at rest or on hover. */
.btn-accent {
  background: var(--gold-soft);
  color: var(--deep2);
  border-color: var(--gold);
}
.btn-accent:hover { background: var(--gold); border-color: var(--gold); color: #16281f; }

/* ---- the header button ------------------------------------------------- */
.cart-button {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  appearance: none;
  border: 0;
  background: none;
  padding: 4px 6px;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.cart-count {
  position: absolute;
  top: -2px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--deep);
  color: var(--on-deep);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ---- the panel --------------------------------------------------------- */
body.cart-open { overflow: hidden; }

.cart-scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(14, 44, 34, 0.42);
  backdrop-filter: blur(2px);
}

.cart-panel {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 61;
  display: flex;
  flex-direction: column;
  width: min(420px, 100vw);
  height: 100dvh;
  background: var(--card);
  border-left: 1px solid var(--line);
  box-shadow: -24px 0 60px -40px rgba(14, 44, 34, 0.6);
}
.cart-panel[hidden] { display: none; }

.cart-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 20px 22px 16px;
  border-bottom: 1px solid var(--line);
}
.cart-head h2 {
  margin: 0;
  font-family: var(--serif);
  font-size: 26px;
  font-weight: 500;
  color: var(--deep2);
}
.cart-close {
  appearance: none;
  border: 0;
  background: none;
  font-size: 30px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 0 4px;
}
.cart-close:hover { color: var(--ink); }

/* The only part that scrolls. */
.cart-body,
.cart-checkout {
  flex: 1;
  overflow-y: auto;
  padding: 18px 22px 24px;
}

/* ---- the lines --------------------------------------------------------- */
.cart-lines { list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; }

.cart-line {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  grid-template-areas: "thumb main qty" "thumb remove remove";
  gap: 4px 14px;
  align-items: start;
}
.cart-thumb {
  grid-area: thumb;
  width: 64px;
  height: 85px;
  object-fit: cover;
  border: 1px solid var(--line);
  background: var(--paper);
}
.cart-thumb-blank { display: block; }
.cart-line-main { grid-area: main; min-width: 0; }
.cart-line-name {
  font-family: var(--serif);
  font-size: 18px;
  color: var(--deep2);
  text-decoration: none;
  display: block;
}
.cart-line-name:hover { text-decoration: underline; }
.cart-line-label { margin: 2px 0 0; font-size: 13px; color: var(--muted); }
.cart-line-price { margin: 4px 0 0; font-size: 14px; font-weight: 600; color: var(--ink); }

.cart-qty {
  grid-area: qty;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--line);
}
.cart-qty button {
  appearance: none;
  border: 0;
  background: none;
  width: 30px;
  height: 30px;
  font-size: 16px;
  line-height: 1;
  color: var(--deep);
  cursor: pointer;
}
.cart-qty button:hover { background: var(--gold-soft); }
.cart-qty span {
  min-width: 26px;
  text-align: center;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.cart-remove {
  grid-area: remove;
  justify-self: start;
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}
.cart-remove:hover { color: var(--danger); }

/* ---- the foot ---------------------------------------------------------- */
.cart-foot {
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.cart-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 0;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
/* The sans, not the display serif. Cormorant Garamond sets old-style figures --
   digits with descenders and uneven heights -- which reads as a flourish on a
   name and as a mistake on a price. Tabular figures on top, so the total does
   not jitter sideways as quantities change. */
.cart-total strong {
  font-family: var(--sans);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
  color: var(--deep2);
}
.cart-note { margin: 10px 0 16px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.cart-foot .btn { width: 100%; text-align: center; }
.cart-foot .btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* A piece that can no longer be ordered: dimmed, struck through, and kept out of
   the total, so the shopper sees what happened rather than hitting a dead end. */
.cart-line-gone { opacity: 0.6; }
.cart-line-gone .cart-line-name { text-decoration: line-through; }
.cart-line-gone-tag { margin: 2px 0 0; font-size: 12px; font-weight: 600; color: #a3432f; }
.cart-gone-note {
  margin: 0 0 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: #a3432f;
}
/* Secondary to Checkout, but clearly a button: an outlined version of the primary
   so a shopper sees it, while the solid Checkout stays the obvious first choice. */
.cart-continue {
  display: block;
  width: 100%;
  margin-top: 10px;
  appearance: none;
  border: 1px solid var(--deep);
  background: transparent;
  color: var(--deep);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 15px 34px;
  text-align: center;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease;
}
.cart-continue:hover {
  background: var(--deep);
  color: var(--on-deep);
}

.cart-empty,
.cart-done { text-align: center; padding: 40px 10px; }
.cart-empty p { color: var(--muted); margin-bottom: 20px; }
/* Flex rather than line-height: a 46px line box on a paragraph that also
   carries the page's inherited line-height leaves the tick sitting high. */
.cart-done-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 14px;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--deep);
  color: var(--on-deep);
  font-size: 22px;
  line-height: 1;
}
.cart-done h3 {
  margin: 0 0 8px;
  font-family: var(--sans);
  font-size: 18px;
  letter-spacing: 0.04em;
  font-weight: 500;
  color: var(--deep2);
}
.cart-done p { color: var(--muted); font-size: 14px; line-height: 1.6; margin-bottom: 20px; }

/* ---- the checkout form ------------------------------------------------- */
.cart-checkout[hidden] { display: none; }
.cart-step {
  margin: 0 0 16px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}
.cart-checkout label {
  display: block;
  margin: 14px 0 5px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink);
}
.cart-optional { font-weight: 400; color: var(--muted); text-transform: none; letter-spacing: 0; }
.cart-checkout input,
.cart-checkout textarea {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--line);
  background: var(--paper);
  font-family: var(--sans);
  font-size: 15px;   /* 16px or above stops iOS zooming the page on focus */
  color: var(--ink);
  border-radius: 0;
}
.cart-checkout input:focus,
.cart-checkout textarea:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}
.cart-checkout textarea { resize: vertical; }
.cart-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* The dial code is a fixed width and the number takes the rest: a select sized
   to its content would jump from "+91 IN" to "+971 AE" and shift the number
   box sideways as it is chosen. */
.cart-phone { display: grid; grid-template-columns: 104px 1fr; gap: 8px; }
.cart-checkout select {
  width: 100%;
  padding: 11px 10px;
  border: 1px solid var(--line);
  background: var(--paper);
  font-family: var(--sans);
  font-size: 15px;
  color: var(--ink);
  border-radius: 0;
  appearance: none;
  /* The native arrow disappears with appearance:none, so it is drawn back on. */
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 15px) calc(50% + 1px), calc(100% - 10px) calc(50% + 1px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 28px;
}
.cart-checkout select:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}
.cart-error {
  margin: 14px 0 0;
  padding: 10px 12px;
  font-size: 13px;
  color: var(--danger);
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  background: color-mix(in srgb, var(--danger) 7%, transparent);
}
.cart-submit { width: 100%; margin-top: 20px; text-align: center; }
.cart-submit:disabled { opacity: 0.6; cursor: default; }
.cart-back {
  display: block;
  width: 100%;
  margin-top: 12px;
  appearance: none;
  border: 0;
  background: none;
  padding: 8px;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}
.cart-back:hover { color: var(--ink); }

/* A phone gets the whole screen: 420px of drawer on a 390px device leaves a
   sliver of page behind it that does nothing but catch stray taps. */
@media (max-width: 520px) {
  .cart-panel { width: 100vw; border-left: 0; }
  .cart-row { grid-template-columns: 1fr; }
  /* The phone row stays side by side: a dial code on its own line reads as a
     separate question rather than as part of the number beside it. */
  .cart-phone { grid-template-columns: 96px 1fr; }
}

@media (prefers-reduced-motion: no-preference) {
  .cart-panel { animation: cart-in 0.28s cubic-bezier(0.22, 1, 0.36, 1); }
  @keyframes cart-in { from { transform: translateX(100%); } to { transform: translateX(0); } }
}

/* =========================================================================
   Virtual try-on
   =========================================================================
   Phone first. The button under Like opens a sheet with three parts: a small
   header naming the piece, the step in the middle, and an action bar fixed at
   the bottom that always shows the one or two things to press next -- big
   targets, short words. On a computer the same sheet is a centred card.
   ========================================================================= */

.tryon-slot { margin-top: 10px; }
.tryon-slot:empty { display: none; }
.tryon-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 18px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--deep);
  background: var(--gold-soft);
  border: 1px solid color-mix(in srgb, var(--gold) 55%, transparent);
  border-radius: 999px;
  cursor: pointer;
}
.tryon-btn svg { width: 17px; height: 17px; color: var(--gold); }
.tryon-btn:hover { border-color: var(--gold); }

.tryon {
  width: min(460px, calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  padding: 0;
  border: 0;
  border-radius: 16px;
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 30px 80px -30px rgba(14, 44, 34, 0.55);
  overflow: hidden;
}
.tryon[open] { display: flex; flex-direction: column; animation: tryon-in 0.22s ease; }
.tryon::backdrop { background: rgba(14, 22, 18, 0.55); }
@keyframes tryon-in { from { opacity: 0; transform: translateY(12px); } }

/* Header: the piece, small, so the shopper knows what they are trying on. */
.tryon-head { display: flex; align-items: center; gap: 12px; padding: 12px 12px 12px 16px; border-bottom: 1px solid var(--line); }
.tryon-head-text { flex: 1; min-width: 0; }
.tryon-title { margin: 0; font-family: var(--sans); font-size: 16px; font-weight: 600; color: var(--deep); }
.tryon-head-name { margin: 2px 0 0; font-size: 13px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tryon-close {
  flex: none;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
}
.tryon-close:hover { background: var(--gold-soft); color: var(--ink); }

/* The step in the middle scrolls if it must; the bar never does. */
.tryon-body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; }

/* The piece and the shopper, side by side. */
.tryon-pair { display: grid; grid-template-columns: minmax(0, 1fr) 14px minmax(0, 1fr); align-items: center; gap: 8px; width: min(100%, 420px); margin: 0 auto; }
.tryon-tile { margin: 0; }
.tryon-tile img, .tryon-you, .tryon-scan {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  max-height: 46dvh;
  object-fit: cover;
  border-radius: 12px;
  background: var(--gold-soft);
}
.tryon-tile figcaption { margin-top: 6px; font-size: 12px; color: var(--muted); text-align: center; }
.tryon-plus { font-size: 18px; color: var(--muted); text-align: center; }
.tryon-you {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 8px;
  border: 1.5px dashed color-mix(in srgb, var(--gold) 70%, transparent);
  color: var(--deep);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.tryon-you svg { width: 34px; height: 34px; color: var(--gold); }
.tryon-hint { margin: 12px 0 0; font-size: 13px; color: var(--muted); text-align: center; }
.tryon.is-framing [data-for="pick"] .tryon-pair, .tryon.is-framing .tryon-hint { display: none; }
/* The photo being worked on: a soft light sweeps across it. */
.tryon-scan { position: relative; overflow: hidden; }
.tryon-scan img { border-radius: 0; max-height: none; height: 100%; }
.tryon-scan::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(110deg, transparent 30%, rgba(255, 255, 255, 0.6) 50%, transparent 70%);
  background-size: 250% 100%;
  animation: tryon-shine 1.6s ease-in-out infinite;
}
@keyframes tryon-shine { from { background-position: 120% 0; } to { background-position: -120% 0; } }

/* The frame: as big as the screen allows, 3:4, the photo moved and zoomed in it. */
.tryon-frame {
  position: relative;
  width: min(100%, calc(min(52dvh, 460px) * 0.75));
  aspect-ratio: 3 / 4;
  margin: 0 auto;
  overflow: hidden;
  border-radius: 12px;
  background: repeating-conic-gradient(var(--gold-soft) 0% 25%, var(--card) 0% 50%) 50% / 18px 18px;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.tryon-frame:active { cursor: grabbing; }
.tryon-frame:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.tryon-frame img { position: absolute; top: 0; left: 0; max-width: none; transform-origin: 0 0; pointer-events: none; }
.tryon-zoom { display: flex; align-items: center; gap: 12px; width: min(100%, 340px); margin: 12px auto 0; }
.tryon-zoom input { flex: 1; height: 28px; accent-color: var(--deep); }
.tryon-zoom-btn {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--deep);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.tryon-frame-hint { margin: 8px 0 0; font-size: 12px; color: var(--muted); text-align: center; }

.tryon-camera { position: relative; overflow: hidden; border-radius: 12px; background: #111; aspect-ratio: 3 / 4; max-height: 56dvh; margin: 0 auto; }
.tryon-camera video { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }

.tryon-working { display: flex; gap: 12px; align-items: center; justify-content: center; margin-top: 14px; padding: 12px 16px; border-radius: 12px; background: var(--gold-soft); }
.tryon-working p { margin: 0; font-size: 14px; line-height: 1.45; color: var(--muted); }
.tryon-working strong { display: block; font-size: 15px; color: var(--ink); }
.tryon-spinner {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--gold) 30%, transparent);
  border-top-color: var(--deep);
  animation: tryon-spin 0.9s linear infinite;
}
@keyframes tryon-spin { to { transform: rotate(360deg); } }

/* The result: the picture as large as fits, the heart on its corner. */
.tryon-result-wrap { position: relative; width: fit-content; max-width: 100%; margin: 0 auto; }
.tryon-result { display: block; max-width: 100%; max-height: 56dvh; border-radius: 12px; background: var(--gold-soft); }
.tryon-like {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  cursor: pointer;
}
.tryon-like svg { width: 24px; height: 24px; }
.tryon-like.is-liked { color: var(--danger); }
.tryon-note { margin: 10px 0 0; font-size: 12px; color: var(--muted); text-align: center; }
.tryon-left { margin: 4px 0 0; font-size: 12px; color: var(--muted); text-align: center; }
.tryon-left:empty { display: none; }
.tryon-error { margin: 0; padding: 16px; border-radius: 12px; font-size: 15px; line-height: 1.45; color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, var(--card)); }
.tryon-privacy { margin: 14px 0 0; font-size: 11px; color: var(--muted); text-align: center; }
.tryon[data-step="done"] .tryon-privacy, .tryon[data-step="working"] .tryon-privacy { display: none; }

/* The action bar: fixed at the bottom, only this step's buttons. */
.tryon-bar {
  flex: none;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--card);
}
.tryon-bar > div { display: none; }
.tryon[data-step="pick"]:not(.is-framing) .tryon-bar-start,
.tryon[data-step="pick"].is-framing .tryon-bar-frame,
.tryon[data-step="details"] .tryon-bar-details,
.tryon[data-step="camera"] .tryon-bar-camera,
.tryon[data-step="done"] .tryon-bar-done,
.tryon[data-step="error"] .tryon-bar-error { display: grid; gap: 10px; }
.tryon[data-step="working"] .tryon-bar { display: none; }
.tryon-bar-row, .tryon-bar-camera, .tryon-bar-done { grid-auto-flow: column; grid-auto-columns: 1fr; }
.tryon-bar-row { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 10px; }
.tryon-bar-frame, .tryon-bar-details { justify-items: center; }
.tryon-details { display: grid; gap: 10px; max-width: 420px; margin: 0 auto; }
.tryon-details-title { margin: 0; font: 500 22px/1.2 var(--serif, Georgia, serif); color: var(--deep); text-align: center; }
.tryon-details-text { margin: 0 0 4px; font-size: 14px; color: var(--muted); text-align: center; }
.tryon-details input[type="text"], .tryon-details input[type="email"], .tryon-details input[type="tel"] {
  width: 100%; box-sizing: border-box; padding: 12px 14px; font: inherit; font-size: 16px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--card); color: var(--ink);
}
.tryon-details-offers { display: flex; gap: 8px; align-items: center; font-size: 14px; color: var(--ink); cursor: pointer; }
.tryon-details-offers input { width: 16px; height: 16px; margin: 0; accent-color: var(--deep); }
.tryon-details-msg { margin: 0; min-height: 1.2em; font-size: 13px; color: var(--muted); }
.tryon-details-msg.is-error { color: var(--danger); }
.tryon[data-step="details"] .tryon-privacy { display: none; }
.tryon-big {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 52px;
  padding: 12px 10px;
  font-size: 13px;
  letter-spacing: 0.06em;
  white-space: nowrap;
  border-radius: 10px;
  text-align: center;
}
.tryon-big svg { width: 20px; height: 20px; flex: none; }
.tryon-consent { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 14px; cursor: pointer; }
.tryon-consent input { width: 20px; height: 20px; flex: none; accent-color: var(--deep); }
.tryon-consent a { color: var(--deep); font-weight: 600; text-underline-offset: 2px; }
/* Pressing "Create my picture" before agreeing gives the tick-box a gentle nudge. */
.tryon-consent.is-nudged { animation: tryon-nudge 0.5s ease; border-radius: 8px; }
@keyframes tryon-nudge {
  0%, 100% { transform: none; background: transparent; }
  20%, 60% { transform: translateX(-4px); background: var(--gold-soft); }
  40%, 80% { transform: translateX(4px); background: var(--gold-soft); }
}
.tryon-link { appearance: none; border: 0; background: none; padding: 4px; font: inherit; font-size: 13px; color: var(--deep); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }

@media (prefers-reduced-motion: reduce) {
  .tryon[open], .tryon-spinner, .tryon-consent.is-nudged, .tryon-scan::after { animation: none; }
}

/* A phone: the whole screen, nothing to scroll past to reach the button. */
@media (max-width: 560px) {
  .tryon {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border-radius: 0;
  }
  .tryon-body { padding: 14px; }
}
/* A short phone (iPhone SE): a smaller frame, so the zoom row and its hint
   stay above the action bar. */
@media (max-height: 640px) {
  .tryon-frame { width: min(100%, calc(42dvh * 0.75)); }
  .tryon-head { padding-block: 8px; }
  .tryon-tile img, .tryon-you, .tryon-scan { max-height: 40dvh; }
}
