/* ============================================================================
   HUSTLERS SCENT
   ----------------------------------------------------------------------------
   Design notes, so later edits do not undo the intent:

   - The page is off-white paper. Depth comes from shadow and scale, never from
     gradients or glass. There is exactly one dark band on the site (the
     discovery sets) and it is the only tonal contrast, which is what makes it
     land.
   - Nothing is evenly spaced by default. The fragrance index is deliberately
     offset, headings are oversized against small labels, and the hero bleeds
     past its column. Symmetry everywhere is the fastest way to look generic.
   - Motion only ever animates transform and opacity. Anything that moves does
     so once, on entry or on touch, and never loops.
   ========================================================================= */

:root {
  --paper:      #f6f3ee;
  --paper-warm: #efeae2;
  --card:       #ffffff;
  --ink:        #111110;
  --ink-soft:   #4a4741;
  --ink-faint:  #8a8478;
  --rule:       rgba(17, 17, 16, .10);
  --rule-soft:  rgba(17, 17, 16, .06);

  /* One accent, used sparingly. Warm brass rather than gold. */
  --accent:     #9a7b3f;

  --shell: min(1560px, 92vw);
  --gutter: clamp(20px, 4.5vw, 72px);

  /* A single easing curve across the whole site. Consistency is what makes
     motion feel designed rather than assembled. */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --fast: 220ms;
  --slow: 420ms;

  /* Layered depth: a tight contact shadow plus a wide ambient one. A single
     blurry shadow is the giveaway of a template. */
  --lift-1: 0 1px 2px rgba(17,17,16,.05), 0 8px 24px -12px rgba(17,17,16,.18);
  --lift-2: 0 2px 4px rgba(17,17,16,.06), 0 24px 60px -24px rgba(17,17,16,.28);
  --lift-3: 0 3px 6px rgba(17,17,16,.08), 0 48px 96px -40px rgba(17,17,16,.38);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

::selection { background: var(--ink); color: var(--paper); }

/* Focus that is actually visible, but only for keyboard users. */
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 2px;
}

.container { width: 100%; max-width: var(--shell); margin: 0 auto; padding: 0 var(--gutter); }

/* ---------------------------------------------------------------- type ---- */

h1, h2, h3, .display {
  font-family: 'Manrope', 'Inter', system-ui, sans-serif;
  font-weight: 800;
  /* Tight tracking is what separates display type from body type set large. */
  letter-spacing: -.035em;
  line-height: .98;
  margin: 0;
  text-wrap: balance;
}

.display-xl { font-size: clamp(44px, 9vw, 150px); }
.display-l  { font-size: clamp(34px, 5.6vw, 92px); }
.display-m  { font-size: clamp(26px, 3.4vw, 54px); letter-spacing: -.03em; }

.lead {
  font-size: clamp(16px, 1.3vw, 22px);
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 46ch;
  margin: 0;
  text-wrap: pretty;
}

/* Small uppercase label. Wide tracking, never larger than 12px. */
.label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}

.rule { height: 1px; background: var(--rule); border: 0; margin: 0; }

/* --------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 26px;
  border-radius: 999px;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--fast) var(--ease), background var(--fast) var(--ease),
              color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.btn:hover { transform: translateY(-2px); box-shadow: var(--lift-1); }
.btn:active { transform: translateY(0); }

.btn-solid { background: var(--ink); color: var(--paper); }
.btn-solid:hover { background: #26251f; }

.btn-quiet { border-color: var(--rule); color: var(--ink-soft); }
.btn-quiet:hover { border-color: var(--ink); color: var(--ink); }

/* Underline that draws in from the left rather than just appearing. */
.link {
  text-decoration: none;
  font-weight: 600;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--fast) var(--ease);
  padding-bottom: 2px;
}
.link:hover { background-size: 100% 1px; }

/* ------------------------------------------------------------------ nav --- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(246, 243, 238, .82);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--fast) var(--ease);
}
.topbar[data-stuck='true'] { border-bottom-color: var(--rule); }

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 68px;
}

.brand {
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: 15px;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-decoration: none;
}

.nav-links { display: flex; gap: 28px; }
.nav-links a {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .02em;
  text-decoration: none;
  color: var(--ink-soft);
  transition: color var(--fast) var(--ease);
}
.nav-links a:hover { color: var(--ink); }

.nav-right { display: flex; align-items: center; gap: 10px; }

.cart-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 18px;
  border-radius: 999px;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  transition: transform var(--fast) var(--ease);
}
.cart-link:hover { transform: translateY(-2px); }

.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}

/* ----------------------------------------------------------------- hero --- */

.hero {
  position: relative;
  padding: clamp(48px, 9vw, 104px) 0 clamp(56px, 8vw, 96px);
  overflow: hidden;
}

/* Oversized wordmark set into the paper. Very low contrast on purpose: it
   should register as texture, not as text you are meant to read. */
.hero-ghost {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding-top: 2vw;
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: clamp(96px, 21vw, 300px);
  letter-spacing: -.05em;
  line-height: .78;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
}

/* Two words on separate depth planes. The far one moves less than the near
   one, which is what sells the parallax as depth rather than as sliding. */
.hero-ghost span {
  display: block;
  color: rgba(17, 17, 16, .085);
  transform: translate3d(var(--gx, 0px), var(--gy, 0px), 0);
  transition: transform 700ms var(--ease);
  will-change: transform;
}
.hero-ghost span:first-child { margin-left: calc(var(--gutter) * -.5); }
.hero-ghost span:last-child {
  margin-left: 14%;
  color: rgba(17, 17, 16, .13);
  --gx: var(--gx2, 0px);
  --gy: var(--gy2, 0px);
}

.hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
}

.hero-copy { position: relative; z-index: 2; }
.hero-copy .display-xl { margin: 18px 0 0; max-width: 12ch; }
.hero-sub { margin-top: 22px; max-width: 34ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }

.hero-meta {
  display: flex;
  gap: clamp(20px, 3vw, 40px);
  margin: 40px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
  max-width: 34ch;
}
.hero-meta > div { min-width: 0; }
.hero-meta dt { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); font-weight: 600; }
.hero-meta dd { margin: 5px 0 0; font-size: 14px; font-weight: 600; }

/* The bottle is allowed to break out of the grid column. Containing it would
   make the hero read as two tidy boxes. */
.hero-stage {
  position: relative;
  perspective: 900px;
  perspective-origin: 50% 45%;
  justify-self: end;
  width: min(92%, 470px);
  margin-right: calc(var(--gutter) * -.2);
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
}

/* Light pooling behind the product, not a gradient panel. */
.hero-stage::before {
  content: '';
  position: absolute;
  inset: 6% 4% 10%;
  border-radius: 50%;
  background: radial-gradient(60% 55% at 50% 42%, #fff 0%, rgba(255,255,255,.7) 42%, rgba(255,255,255,0) 72%);
}

/* Two independent effects compose into one transform: --drift comes from
   scroll, --tilt from the pointer. Composing them in CSS rather than string
   concatenating in JS means neither can clobber the other. Both default to
   identity so the element is correct before any script runs. */
/* ---- the 3D stage ----------------------------------------------------
   The bottle photo is a flat image, so it cannot turn to show another side.
   What it can do is behave like a rigid card under a moving viewpoint: a real
   perspective projection, rotating about Y, catching a moving specular sheen
   across its face. That is the part the eye actually reads as three
   dimensional, and it holds up because the geometry is genuine even though
   the subject is a photograph.  */
.hero-card {
  position: relative;
  width: 76%;
  border-radius: 20px;
  overflow: hidden;
  background: #fff;
  transform-style: preserve-3d;
  box-shadow: var(--lift-3);
  --spin: rotateY(0deg);
  --tilt: rotateX(0deg) rotateY(0deg) translateZ(0px);
  --drift: translate3d(0, 0, 0);
  /* Resting angle. Without it the card settles square-on and the whole
     effect disappears the moment you stop moving. */
  transform: var(--drift) rotateY(-11deg) rotateX(3deg) var(--spin) var(--tilt);
  transition: transform 260ms var(--ease);
  will-change: transform;
  animation: intro-spin 1400ms var(--ease) both;
}

/* The intro. Swings in from a steep angle and settles, once, on load. */
@keyframes intro-spin {
  from { opacity: 0; transform: rotateY(-60deg) rotateX(8deg) translateX(10%) scale(.92); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: var(--drift) rotateY(-11deg) rotateX(3deg) var(--spin) var(--tilt); }
}

/* Light travelling across the face as it turns. Sits above the photo, below
   nothing else, and is purely decorative. */
.hero-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, rgba(255,255,255,0) 38%, rgba(255,255,255,.55) 50%, rgba(255,255,255,0) 62%);
  transform: translateX(var(--sheen, -60%));
  transition: transform 260ms var(--ease);
  pointer-events: none;
  mix-blend-mode: overlay;
}

.hero-bottle {
  position: relative;
  width: 100%;
  height: auto;
  object-fit: contain;
  display: block;
}

/* A pressed-in contact shadow so the bottle sits on a surface rather than
   floating in a void. Elliptical and tight, the way a real one falls. */
.hero-shadow {
  position: absolute;
  left: 50%;
  bottom: 9%;
  width: 46%;
  height: 26px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(17,17,16,.30) 0%, rgba(17,17,16,.10) 55%, rgba(17,17,16,0) 78%);
  filter: blur(5px);
}

/* -------------------------------------------------------------- sections -- */

.section { padding: clamp(56px, 8vw, 108px) 0; }

.section-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 20px 40px;
  /* Aligned to the top of the heading block, not its bottom: with a rating
     line underneath, "end" left the button floating mid-air. */
  align-items: start;
  margin-bottom: clamp(28px, 4vw, 52px);
}
.section-head .label { margin-bottom: 14px; }
.section-head .lead { margin-top: 16px; }
.section-head > .btn { margin-top: 6px; }

/* ------------------------------------------------------- discovery band --- */

/* The one dark moment on the site. */
.band {
  background: #14140f;
  color: #f2efe8;
  padding: clamp(56px, 8vw, 104px) 0;
}
.band .label { color: rgba(242,239,232,.5); }
.band .lead { color: rgba(242,239,232,.72); }
.band .btn { border-color: rgba(242,239,232,.34); color: #f2efe8; }
.band .btn:hover { border-color: #f2efe8; }
.band .btn-solid { background: #f2efe8; color: #14140f; border-color: #f2efe8; }
.band .btn-solid:hover { background: #fff; }
.band :focus-visible { outline-color: #f2efe8; }

.sets {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2.4vw, 32px);
}

.set {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(22px, 2.6vw, 34px);
  border: 1px solid rgba(242,239,232,.14);
  border-radius: 18px;
  background: rgba(255,255,255,.025);
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  transition: transform var(--slow) var(--ease), border-color var(--slow) var(--ease),
              background var(--slow) var(--ease);
}
.set:hover { transform: translateY(-5px); border-color: rgba(242,239,232,.3); background: rgba(255,255,255,.05); }

/* The box photos are shot on white with no alpha, so against the dark band
   they read as glaring rectangles. Framing them in their own white card makes
   the backdrop part of the design instead of a mistake. */
.set-media {
  position: relative;
  perspective: 1200px;
  aspect-ratio: 4 / 3;
  border-radius: 14px;
  overflow: hidden;
  background: #fff;
  margin-bottom: 24px;
}
.set-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--slow) var(--ease);
}
.set:hover .set-media img { transform: translateY(-6px) scale(1.03); }

.set-top { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.set-name { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(19px, 2vw, 24px); letter-spacing: -.025em; }
.set-price { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 17px; white-space: nowrap; }

/* Contents as a real list, because what is in the box is the selling point. */
.set-contents { list-style: none; margin: 20px 0 0; padding: 18px 0 0; border-top: 1px solid rgba(242,239,232,.14); }
.set-contents li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 5px 0;
  font-size: 14px;
  color: rgba(242,239,232,.8);
}
.set-contents b { font-family: 'Manrope', sans-serif; font-weight: 800; color: #f2efe8; font-size: 13px; letter-spacing: .02em; }

.set-foot { margin-top: 22px; display: flex; align-items: center; gap: 12px; }

/* ------------------------------------------------------ fragrance index --- */

/* Deliberately not a uniform grid: rows alternate which side the image sits
   on, and the two row widths differ. */
.fragrances { display: flex; flex-direction: column; gap: clamp(28px, 5vw, 72px); }

.frag {
  display: grid;
  grid-template-columns: minmax(0, .68fr) minmax(0, 1.32fr);
  gap: clamp(20px, 4vw, 60px);
  align-items: center;
  text-decoration: none;
  color: inherit;
}
.frag:nth-child(odd)  { width: min(100%, 1080px); }
.frag:nth-child(even) { width: min(100%, 1010px); margin-left: auto; grid-template-columns: minmax(0, 1.32fr) minmax(0, .68fr); }
.frag:nth-child(even) .frag-media { order: 2; }
.frag:nth-child(even) .frag-body { order: 1; justify-self: end; }

.frag-media {
  position: relative;
  perspective: 1200px;
  aspect-ratio: 4 / 5;
  border-radius: 20px;
  background: #fff;
  display: grid;
  place-items: center;
  overflow: hidden;
  box-shadow: var(--lift-1);
  transition: box-shadow var(--slow) var(--ease), transform var(--slow) var(--ease);
}
.frag:hover .frag-media { box-shadow: var(--lift-3); transform: translateY(-4px); }

.frag-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 7%;
  transition: transform var(--slow) var(--ease);
}
.frag:hover .frag-media img { transform: scale(1.055) translateY(-6px); }

/* Numeral sunk into the card, behind the product. */
.frag {
  position: relative;
  /* Room for the ghost accord, so it can never sit under the price line. */
  padding-bottom: clamp(26px, 4.2vw, 58px);
}
.frag-media, .frag-body { position: relative; z-index: 1; }

/* The row's empty quadrant carries the scent's key accord as a ghost word,
   echoing the hero wordmark. It is aligned to the text column and clipped to
   the row, so it reads as set type rather than as something that slid off. */
.frag-ghost {
  position: absolute;
  z-index: 0;
  bottom: 0;
  width: 66%;
  font-family: Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-size: clamp(30px, 4.3vw, 66px);
  letter-spacing: -.02em;
  line-height: 1;
  color: rgba(17, 17, 16, .08);
  white-space: nowrap;
  overflow: hidden;
  pointer-events: none;
  user-select: none;
}
/* Odd rows put the copy in the right-hand column, even rows in the left, so
   the word starts exactly where its paragraph does. */
.frag:nth-child(odd) .frag-ghost  { left: 34%; padding-left: clamp(20px, 4vw, 60px); }
.frag:nth-child(even) .frag-ghost { left: 0; text-align: right; padding-right: clamp(20px, 4vw, 60px); }

@media (max-width: 1000px) {
  .frag { padding-bottom: clamp(22px, 6vw, 40px); }
  .frag-ghost, .frag:nth-child(odd) .frag-ghost, .frag:nth-child(even) .frag-ghost {
    left: 0; width: 100%; padding: 0; text-align: left; font-size: clamp(28px, 8vw, 44px);
  }
}
.frag-body { min-width: 0; }
.frag-name { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(28px, 4.2vw, 46px); letter-spacing: -.035em; line-height: 1; margin: 14px 0 0; }
.frag-note { margin: 14px 0 0; color: var(--ink-soft); font-size: 15px; max-width: 40ch; }
.frag-foot { display: flex; align-items: center; gap: 20px; margin-top: 26px; }
.frag-price { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 20px; }

/* Accord chips: three words, hairline, no icons. */
.accords { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 18px; }
.accord {
  font-size: 12px;
  letter-spacing: .04em;
  padding: 5px 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-soft);
}

/* -------------------------------------------------------------- reviews --- */

/* A grid, not CSS columns. With five tall phone photos the column balancer
   left one column empty and orphaned a single image, which is what "the
   reviews are messed up" was. The first photo spans a 2x2 block so the wall
   is still deliberately uneven rather than a tidy row of five. */
.reviews {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 18px);
}
.review {
  position: relative;
  margin: 0;
  aspect-ratio: 3 / 4;
  border-radius: 14px;
  overflow: hidden;
  background: var(--paper-warm);
  box-shadow: var(--lift-1);
  transition: transform var(--slow) var(--ease), box-shadow var(--slow) var(--ease);
}
.review:hover { transform: translateY(-4px); box-shadow: var(--lift-2); }
/* cover + absolute fill, so every tile is the same shape whatever the photo. */
.review img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--slow) var(--ease);
}
.review:hover img { transform: scale(1.04); }

/* ---------------------------------------------------------- product page -- */

.crumbs { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 12px; color: var(--ink-faint); padding: 22px 0 0; }
.crumbs a { text-decoration: none; }
.crumbs a:hover { color: var(--ink); }

.pdp {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(28px, 5vw, 80px);
  align-items: start;
  padding: clamp(20px, 3vw, 40px) 0 clamp(56px, 8vw, 104px);
}

.pdp-stage {
  position: sticky;
  perspective: 1200px;
  top: 96px;
  aspect-ratio: 1 / 1;
  border-radius: 24px;
  background: #fff;
  display: grid;
  place-items: center;
  overflow: hidden;
  box-shadow: var(--lift-2);
}
/* contain + a height cap so a wide image (the set boxes) and a tall one (the
   bottles) both sit inside the same square stage without distorting. */
.pdp-stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 6%;
  --tilt: rotateX(0deg) rotateY(0deg) translateZ(0px);
  transform: var(--tilt);
  transition: transform 260ms var(--ease);
  will-change: transform;
}
/* The set boxes are landscape, so they need the width rather than the height. */
.pdp-stage[data-shape='wide'] img { width: 100%; height: 100%; }

.pdp-title { margin: 12px 0 0; }
.pdp-sub { margin: 14px 0 0; color: var(--ink-faint); font-size: 14px; letter-spacing: .01em; }
.pdp-price { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(24px, 3vw, 32px); margin: 24px 0 0; }
.pdp-desc { margin: 22px 0 0; color: var(--ink-soft); max-width: 46ch; }
.pdp-actions { display: flex; flex-wrap: wrap; gap: 12px; margin: 30px 0 0; }

.spec { margin: 32px 0 0; padding: 22px 0 0; border-top: 1px solid var(--rule); display: grid; gap: 16px; }
.spec-row { display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 18px; align-items: baseline; }
.spec-row dt { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); font-weight: 600; }
.spec-row dd { margin: 0; font-size: 15px; color: var(--ink-soft); }

/* The pyramid: a vertical rail with the three stages hung off it. Reads as a
   structure rather than three bulleted lists. */
.pyramid { margin: 40px 0 0; padding: 28px 0 0; border-top: 1px solid var(--rule); }
.pyramid-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 26px; }

.stages { position: relative; padding-left: 26px; }
.stages::before {
  content: '';
  position: absolute;
  left: 4px; top: 6px; bottom: 6px;
  width: 1px;
  background: linear-gradient(180deg, var(--accent) 0%, var(--rule) 100%);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 900ms var(--ease) 120ms;
}
.pyramid.in .stages::before { transform: scaleY(1); }

.stage {
  position: relative;
  padding: 0 0 26px;
  transition: transform var(--fast) var(--ease);
  cursor: default;
}
.stage:hover { transform: translateX(5px); }
.stage:hover .stage-name { color: var(--accent); }
.stage::after {
  content: '';
  position: absolute;
  left: -26px; top: 7px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  transform: scale(.4);
  transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.stage:hover::after { opacity: 1; transform: scale(2.1); }
.stage:last-child { padding-bottom: 0; }
.stage::before {
  content: '';
  position: absolute;
  left: -26px; top: 7px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--accent);
}
.stage[data-stage='top']::before { background: var(--accent); }
.stage-name { transition: color var(--fast) var(--ease); font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); font-weight: 600; }
.stage-notes { margin: 8px 0 0; font-family: 'Manrope', sans-serif; font-weight: 700; font-size: clamp(17px, 2vw, 21px); letter-spacing: -.02em; }

/* --------------------------------------------------------- collection ----- */

.grid-products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  gap: clamp(16px, 2.4vw, 30px);
}

.pcard { display: flex; flex-direction: column; text-decoration: none; color: inherit; }
.pcard-media {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: 16px;
  background: #fff;
  display: grid;
  place-items: center;
  overflow: hidden;
  box-shadow: var(--lift-1);
  transition: box-shadow var(--slow) var(--ease), transform var(--slow) var(--ease);
}
.pcard:hover .pcard-media { box-shadow: var(--lift-2); transform: translateY(-4px); }
.pcard-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; padding: 9%; transition: transform var(--slow) var(--ease); }
.pcard:hover .pcard-media img { transform: scale(1.05) translateY(-5px); }
.pcard-body { padding: 16px 2px 0; display: flex; justify-content: space-between; gap: 14px; align-items: baseline; }
.pcard-name { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 16px; letter-spacing: -.02em; }
.pcard-price { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 15px; white-space: nowrap; }
.pcard-note { padding: 6px 2px 0; font-size: 13px; color: var(--ink-faint); }

/* --------------------------------------------------------------- cart ----- */

.cart-wrap { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, .8fr); gap: clamp(20px, 3vw, 44px); align-items: start; }
.cart-panel { background: var(--card); border: 1px solid var(--rule-soft); border-radius: 18px; padding: clamp(18px, 2.4vw, 28px); box-shadow: var(--lift-1); }
.cart-line { display: grid; grid-template-columns: 84px minmax(0, 1fr) auto auto; gap: 18px; align-items: center; padding: 18px 0; border-bottom: 1px solid var(--rule-soft); }
.cart-line:last-of-type { border-bottom: 0; }
.cart-thumb { width: 84px; aspect-ratio: 1; border-radius: 10px; background: var(--paper-warm); display: grid; place-items: center; overflow: hidden; }
.cart-thumb img { width: 76%; max-height: 82%; object-fit: contain; }
.cart-name { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 15px; letter-spacing: -.02em; }
.cart-unit { font-size: 13px; color: var(--ink-faint); margin-top: 3px; }
.qty { width: 62px; height: 40px; text-align: center; border: 1px solid var(--rule); border-radius: 10px; background: var(--paper); font: inherit; font-size: 14px; }
.cart-total { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 16px; white-space: nowrap; }
.summary-row { display: flex; justify-content: space-between; gap: 16px; padding: 12px 0; font-size: 14px; color: var(--ink-soft); }
.summary-row.total { border-top: 1px solid var(--rule); margin-top: 8px; padding-top: 18px; font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 19px; color: var(--ink); }
.icon-btn { border: 0; background: none; padding: 6px; cursor: pointer; color: var(--ink-faint); border-radius: 8px; transition: color var(--fast) var(--ease); }
.icon-btn:hover { color: var(--ink); }

.empty { text-align: center; padding: clamp(48px, 9vw, 110px) 0; }
.empty .lead { margin: 16px auto 0; }

/* --------------------------------------------------------------- prose ---- */

.prose { max-width: 62ch; }
.prose p { color: var(--ink-soft); }
.prose h2 { font-size: 24px; margin: 32px 0 10px; }

/* -------------------------------------------------------------- footer ---- */

.site-foot { margin-top: auto; border-top: 1px solid var(--rule); padding: clamp(36px, 5vw, 64px) 0 32px; }
.foot-grid { display: flex; flex-wrap: wrap; gap: 28px; justify-content: space-between; align-items: flex-start; }
.foot-links { display: flex; flex-wrap: wrap; gap: 22px; }
.foot-links a { font-size: 13px; color: var(--ink-soft); text-decoration: none; }
.foot-links a:hover { color: var(--ink); }
.ig {
  display: inline-grid;
  place-items: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.ig:hover { background: var(--ink); color: var(--paper); transform: translateY(-2px); }
.foot-fine { margin-top: 34px; font-size: 12px; color: var(--ink-faint); }

/* --------------------------------------------------------------- toast ---- */

#toast-container { position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%); z-index: 90; display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none; }
.toast {
  background: var(--ink);
  color: var(--paper);
  padding: 12px 20px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  box-shadow: var(--lift-2);
  animation: toast-in 320ms var(--ease);
}
.toast.error { background: #7a2620; }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(.97); } to { opacity: 1; transform: none; } }

/* -------------------------------------------------------------- motion ---- */

/* Reveal on entry. --i staggers siblings; the values are small because a long
   stagger is the thing that makes a page feel auto-generated. */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
  transition-delay: calc(var(--i, 0) * 65ms);
}
[data-reveal].in { opacity: 1; transform: none; }

/* Images settle rather than pop: a touch of scale released on entry. */
[data-reveal='media'] { transform: translateY(22px) scale(.985); }
[data-reveal='media'].in { transform: none; }

/* If scripting never runs, nothing may stay hidden. */
.no-js [data-reveal] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero-card { animation: none; }
  .hero-card::after { display: none; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .hero-bottle { transform: none !important; }
}

/* ----------------------------------------------------------- responsive --- */

@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: 1fr; gap: 8px; }
  .hero-copy { order: 2; }
  .hero-copy .display-xl { max-width: none; }
  .hero-stage { order: 1; justify-self: center; width: min(80%, 420px); margin: 0 0 28px; }
  .hero-meta { max-width: none; }
  .pdp { grid-template-columns: 1fr; }
  .pdp-stage { position: static; }
  .frag, .frag:nth-child(even) { grid-template-columns: 1fr; width: 100%; margin-left: 0; }
  .frag:nth-child(even) .frag-media { order: 0; }
  .reviews { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cart-wrap { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .nav-links { display: none; }
  .section-head { grid-template-columns: 1fr; align-items: start; }
  .sets { grid-template-columns: 1fr; }
  .reviews { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .review-img { aspect-ratio: 1 / 1; }
  .review-body { padding: 12px 13px 15px; }
  .review-body p { font-size: 12.5px; }
  .cart-line { grid-template-columns: 64px minmax(0, 1fr) auto; row-gap: 10px; }
  .cart-thumb { width: 64px; }
  .cart-total { grid-column: 2 / -1; }
  .hero-ghost { font-size: 34vw; }
  .spec-row { grid-template-columns: 100px minmax(0, 1fr); gap: 12px; }
}

/* -------------------------------------------------------------- rating ---- */

.rating { display: flex; align-items: center; gap: 12px; margin-top: 18px; font-size: 13px; color: var(--ink-soft); }
.stars { display: inline-flex; gap: 3px; }
.stars svg { width: 15px; height: 15px; fill: var(--accent); }

/* The wordmark parts to let the hero in. */
@keyframes ghost-in-l {
  from { opacity: 0; transform: translate3d(-7vw, 0, 0); }
  to   { opacity: 1; transform: translate3d(var(--gx, 0px), var(--gy, 0px), 0); }
}
@keyframes ghost-in-r {
  from { opacity: 0; transform: translate3d(7vw, 0, 0); }
  to   { opacity: 1; transform: translate3d(var(--gx, 0px), var(--gy, 0px), 0); }
}
.hero-ghost span:first-child { animation: ghost-in-l 1300ms var(--ease) backwards; }
.hero-ghost span:last-child  { animation: ghost-in-r 1300ms var(--ease) 140ms backwards; }

@media (prefers-reduced-motion: reduce) {
  .hero-ghost span { animation: none !important; }
}

/* ---- reviews: photo above, stars and the customer's words below --------- */
.review { display: flex; flex-direction: column; aspect-ratio: auto; }
.review-img { position: relative; aspect-ratio: 3 / 4; overflow: hidden; background: var(--paper-warm); }
.review:first-child .review-img { aspect-ratio: 3 / 4; }
.review-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform var(--slow) var(--ease); }
.review:hover .review-img img { transform: scale(1.04); }
.review-body { background: var(--card); padding: 14px 16px 18px; flex: 1; }
.review-body p { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-soft); }

/* ==========================================================================
   THE CATALOG
   --------------------------------------------------------------------------
   Once the reel has run, the page stops performing. No pinning, no scroll
   driving, no beats: a plain grid that scrolls the way a shop should, with
   every product reachable and buyable in one place. The acts are the pitch;
   this is the counter.
   ========================================================================== */

.catalog { padding: clamp(56px, 8vw, 104px) 0 clamp(64px, 9vw, 120px); }
.catalog .section-head { margin-bottom: clamp(24px, 3vw, 40px); }
.catalog-group + .catalog-group { margin-top: clamp(40px, 5vw, 68px); }
.catalog-group > .label { margin-bottom: 18px; }
/* Explicit counts: auto-fill left the fourth fragrance orphaned on its own
   row at common desktop widths. */
.catalog-group .grid-products { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.catalog-group:last-child .grid-products { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 620px; }
@media (max-width: 1000px) { .catalog-group .grid-products { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) {
  .catalog-group .grid-products,
  .catalog-group:last-child .grid-products { grid-template-columns: 1fr; }
}

.pcard-actions { display: flex; gap: 8px; padding-top: 12px; }
.pcard-actions .btn { min-height: 40px; padding: 0 16px; font-size: 13px; }



/* ==========================================================================
   STATIC BUILD
   --------------------------------------------------------------------------
   This version has no scroll-driven acts, no pinning and no scroll wash. The
   hero is an ordinary two-column section and everything below it scrolls the
   way a shop should. Motion is limited to reveal-on-entry, hover, and a
   pointer tilt on the hero card.
   ========================================================================== */

.hero { position: relative; padding: clamp(48px, 8vw, 110px) 0 clamp(56px, 8vw, 100px); overflow: hidden; }

.hero-ghost {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding-top: 2vw;
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: clamp(90px, 13vw, 300px);
  letter-spacing: -.05em;
  line-height: .78;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
}
.hero-ghost span {
  display: block;
  color: rgba(17, 17, 16, .055);
  transform: translate3d(var(--gx, 0px), var(--gy, 0px), 0);
  transition: transform 700ms var(--ease);
  will-change: transform;
}
.hero-ghost span:first-child { margin-left: calc(var(--gutter) * -.5); }
.hero-ghost span:last-child {
  margin-left: 14%;
  color: rgba(17, 17, 16, .09);
  --gx: var(--gx2, 0px);
  --gy: var(--gy2, 0px);
}

.hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
}
.hero-copy { position: relative; z-index: 2; }
.hero-copy .display-xl { margin: 18px 0 0; max-width: 12ch; }
.hero-sub { margin-top: 22px; max-width: 36ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }

.hero-meta {
  display: flex;
  gap: clamp(20px, 3vw, 44px);
  margin: 40px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
  max-width: 40ch;
}
.hero-meta dt { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); font-weight: 600; }
.hero-meta dd { margin: 5px 0 0; font-size: 14px; font-weight: 600; }

.hero-stage {
  position: relative;
  justify-self: end;
  width: min(88%, 480px);
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  perspective: 1100px;
}
.hero-card {
  position: relative;
  width: 82%;
  border-radius: 20px;
  overflow: hidden;
  background: #fff;
  box-shadow: var(--lift-3);
  --drift: translate3d(0, 0, 0);
  --tilt: rotateX(0deg) rotateY(0deg) translateZ(0px);
  transform: var(--drift) rotateY(-6deg) var(--tilt);
  /* Eased behind the pointer rather than glued to it, so it reads as an
     object with weight. */
  transition: transform 260ms var(--ease);
  will-change: transform;
}
.hero-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, rgba(255,255,255,0) 38%, rgba(255,255,255,.5) 50%, rgba(255,255,255,0) 62%);
  transform: translateX(var(--sheen, -60%));
  transition: transform 260ms var(--ease);
  pointer-events: none;
  mix-blend-mode: overlay;
}
.hero-bottle { display: block; width: 100%; height: auto; }

.hero-shadow {
  position: absolute;
  left: 50%; bottom: 4%;
  width: 46%; height: 26px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(17,17,16,.26) 0%, rgba(17,17,16,.09) 55%, rgba(17,17,16,0) 78%);
  filter: blur(5px);
}

/* ---- the dark band paints its own background here ---- */
.band { background: #14140f; color: #f2efe8; padding: clamp(56px, 8vw, 104px) 0; }
.band .label { color: rgba(242,239,232,.5); }
.band .lead { color: rgba(242,239,232,.72); }
.band .btn { border-color: rgba(242,239,232,.34); color: #f2efe8; }
.band .btn:hover { border-color: #f2efe8; }
.band .btn-solid { background: #f2efe8; color: #14140f; border-color: #f2efe8; }
.band :focus-visible { outline-color: #f2efe8; }

.sets { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(16px, 2.4vw, 32px); }
.set {
  position: relative; display: flex; flex-direction: column;
  padding: clamp(22px, 2.6vw, 34px);
  border: 1px solid rgba(242,239,232,.14);
  border-radius: 18px;
  background: rgba(255,255,255,.025);
  text-decoration: none; color: inherit; overflow: hidden;
  transition: transform var(--slow) var(--ease), border-color var(--slow) var(--ease), background var(--slow) var(--ease);
}
.set:hover { transform: translateY(-5px); border-color: rgba(242,239,232,.3); background: rgba(255,255,255,.05); }
.set-media { position: relative; aspect-ratio: 4 / 3; border-radius: 14px; overflow: hidden; background: #fff; margin-bottom: 24px; }
.set-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform var(--slow) var(--ease); }
.set:hover .set-media img { transform: scale(1.03); }
.set-top { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.set-name { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(19px, 2vw, 26px); letter-spacing: -.025em; }
.set-price { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 18px; white-space: nowrap; }
.set-contents { list-style: none; margin: 20px 0 0; padding: 18px 0 0; border-top: 1px solid rgba(242,239,232,.14); }
.set-contents li { display: flex; align-items: baseline; gap: 12px; padding: 5px 0; font-size: 14px; color: rgba(242,239,232,.8); }
.set-contents b { font-family: 'Manrope', sans-serif; font-weight: 800; color: #f2efe8; font-size: 13px; letter-spacing: .02em; }
.set-foot { margin-top: 22px; display: flex; align-items: center; gap: 12px; }

/* ---- staggered fragrance rows ---- */
.fragrances { display: flex; flex-direction: column; gap: clamp(28px, 5vw, 72px); }
.frag {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, .68fr) minmax(0, 1.32fr);
  gap: clamp(20px, 4vw, 60px);
  align-items: center;
  text-decoration: none; color: inherit;
  padding-bottom: clamp(26px, 4.2vw, 58px);
}
.frag-media, .frag-body { position: relative; z-index: 1; }
.frag:nth-child(odd)  { width: min(100%, 1120px); }
.frag:nth-child(even) { width: min(100%, 1050px); margin-left: auto; grid-template-columns: minmax(0, 1.32fr) minmax(0, .68fr); }
.frag:nth-child(even) .frag-media { order: 2; }
.frag:nth-child(even) .frag-body { order: 1; justify-self: end; text-align: right; }
.frag:nth-child(even) .frag-note { margin-left: auto; }
.frag:nth-child(even) .accords, .frag:nth-child(even) .frag-foot { justify-content: flex-end; }

.frag-media {
  position: relative; aspect-ratio: 4 / 5; border-radius: 20px; background: #fff;
  overflow: hidden;
  box-shadow: var(--lift-1);
  transition: box-shadow var(--slow) var(--ease), transform var(--slow) var(--ease);
}
.frag:hover .frag-media { box-shadow: var(--lift-3); transform: translateY(-4px); }
.frag-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; padding: 7%; transition: transform var(--slow) var(--ease); }
.frag:hover .frag-media img { transform: scale(1.04); }

.frag-body { min-width: 0; }
.frag-name { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: clamp(28px, 4.2vw, 66px); letter-spacing: -.035em; line-height: 1; margin: 14px 0 0; }
.frag-note { margin: 14px 0 0; color: var(--ink-soft); font-size: clamp(15px, 1.2vw, 18px); max-width: 40ch; }
.frag-foot { display: flex; align-items: center; gap: 20px; margin-top: 26px; }
.frag-price { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 22px; }

/* The ghost accord filling each row's empty quadrant. */
.frag-ghost {
  position: absolute; z-index: 0; bottom: 0; width: 66%;
  font-family: Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-size: clamp(30px, 4.3vw, 78px);
  letter-spacing: -.02em; line-height: 1;
  color: rgba(17, 17, 16, .08);
  white-space: nowrap; overflow: hidden;
  pointer-events: none; user-select: none;
}
.frag:nth-child(odd) .frag-ghost  { left: 34%; padding-left: clamp(20px, 4vw, 60px); }
.frag:nth-child(even) .frag-ghost { left: 0; text-align: right; padding-right: clamp(20px, 4vw, 60px); }

/* ---- reviews: photo over stars and the customer's words ---- */
.reviews { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: clamp(10px, 1.4vw, 18px); }
.review {
  display: flex; flex-direction: column;
  border-radius: 14px; overflow: hidden;
  background: var(--card);
  box-shadow: var(--lift-1);
  transition: transform var(--slow) var(--ease), box-shadow var(--slow) var(--ease);
}
.review:hover { transform: translateY(-4px); box-shadow: var(--lift-2); }
.review-img { position: relative; aspect-ratio: 3 / 4; overflow: hidden; background: var(--paper-warm); }
.review-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform var(--slow) var(--ease); }
.review:hover .review-img img { transform: scale(1.04); }
.review-body { padding: 14px 16px 18px; flex: 1; }
.review-body p { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-soft); }

@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: 1fr; gap: 8px; }
  .hero-copy { order: 2; }
  .hero-copy .display-xl { max-width: none; }
  .hero-stage { order: 1; justify-self: center; width: min(80%, 420px); margin: 0 0 28px; }
  .hero-meta { max-width: none; }
  .frag, .frag:nth-child(even) { grid-template-columns: 1fr; width: 100%; margin-left: 0; }
  .frag:nth-child(even) .frag-media { order: 0; }
  .frag:nth-child(even) .frag-body { order: 0; justify-self: start; text-align: left; }
  .frag:nth-child(even) .frag-note { margin-left: 0; }
  .frag:nth-child(even) .accords, .frag:nth-child(even) .frag-foot { justify-content: flex-start; }
  .frag-ghost, .frag:nth-child(odd) .frag-ghost, .frag:nth-child(even) .frag-ghost {
    left: 0; width: 100%; padding: 0; text-align: left; font-size: clamp(28px, 8vw, 44px);
  }
  .reviews { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .sets { grid-template-columns: 1fr; }
  .reviews { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .review-img { aspect-ratio: 1 / 1; }
  .hero-ghost { font-size: 30vw; }
}
