/* ============================================================
   product card + bestsellers rail + just landed
   ============================================================ */
.card{position:relative;display:flex;flex-direction:column}
.card__media{
  position:relative;overflow:hidden;background:var(--ivory);aspect-ratio:4/5;
  border-radius:var(--radius-md);
}
.card__media img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform 1.2s var(--slow),opacity .7s var(--ease);
}
.card__media .alt{opacity:0}
.card:hover .card__media .main{opacity:0;transform:scale(1.03)}
.card:hover .card__media .alt{opacity:1;transform:scale(1.03)}

/* badge system: status top-left, discount top-right, equal insets */
.flags{position:absolute;top:16px;left:16px;z-index:2;display:flex;flex-direction:column;align-items:flex-start;gap:6px}
.flags--deal{left:auto;right:16px;align-items:flex-end}
.flag{
  border-radius:var(--radius-sm);
  font-size:10px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  background:var(--milk);color:var(--ink);padding:5px 9px;
}
.flag--new{background:var(--ink);color:var(--milk)}
.flag--off{background:var(--accent);color:#fff}

/* the heart moves to the lower corner so it never meets the discount badge */
.wish{
  position:absolute;right:10px;bottom:56px;z-index:3;width:36px;height:36px;display:grid;place-items:center;
  color:var(--ink);background:rgba(252,250,247,.86);border-radius:50%;
  opacity:0;transform:translateY(6px);
  transition:opacity .4s var(--ease),transform .4s var(--slow),color .3s,background .3s;
}
.wish:hover{background:var(--milk)}
.card:hover .wish,.wish:focus-visible,.wish.on{opacity:1;transform:none}
.wish svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.3}
.wish.on svg{fill:var(--accent);stroke:var(--accent)}

.qadd{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  height:46px;background:rgba(252,250,247,.95);backdrop-filter:blur(6px);
  display:flex;align-items:center;justify-content:center;gap:9px;
  font-size:var(--t-label);font-weight:500;letter-spacing:.16em;text-transform:uppercase;
  transform:translateY(100%);transition:transform .5s var(--slow),background .3s,color .3s;
}
.card:hover .qadd{transform:none}
.qadd:hover{background:var(--ink);color:var(--milk)}
.qadd.done{background:var(--accent);color:#fff;transform:none}

/* the info area fills what is left of the card so the price row lands on one
   line across a grid row, however many lines a product name takes */
.card__info{padding-top:15px;display:flex;flex-direction:column;gap:3px;flex:1}
.card__brand{font-size:var(--t-label);letter-spacing:.14em;text-transform:uppercase;color:var(--ink-45)}
.card__name{font-size:clamp(.95rem,.35vw + .88rem,1.0625rem);font-weight:500;letter-spacing:-.005em;line-height:1.35}
.card__desc{font-size:var(--t-meta);color:var(--ink-45);line-height:1.45}
.card__row{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-top:auto;padding-top:7px}
.price{font-size:var(--t-meta);font-weight:500;font-variant-numeric:tabular-nums;letter-spacing:.01em}
.price s{color:var(--ink-25);font-weight:400;margin-left:8px}
.rate{display:inline-flex;align-items:center;gap:6px;font-size:var(--t-label);color:var(--ink-45);letter-spacing:.06em}
.rate .stars{letter-spacing:.08em;color:var(--ink);font-size:10px}

/* ---------- bestsellers ---------- */
/* white section; the band above it does the separating */
.best{
  background:var(--milk);
  padding-block:var(--space-lg) 0;
}
.best__rail{margin-inline:0}
.best .rail>.card{width:clamp(230px,24vw,336px)}
/* the link sits opposite the arrows that move the same rail */
.best__foot{display:flex;align-items:center;justify-content:space-between;gap:20px;
  margin-top:clamp(26px,3vw,42px)}

/* phone: one card at a time, the next one peeking so the row reads as swipeable.
   Snap is mandatory by width too — (hover:none) alone misses hybrid devices. */
@media (max-width:700px){
  .best .rail>.card{width:min(78vw,320px)}
  .best__rail{
    scroll-snap-type:x mandatory;
    /* the rail stopped at the container edge, so the next card was sliced off
       against an 18px strip of page. It runs under the screen edge instead. */
    margin-inline:calc(var(--gutter) * -1);padding-inline:var(--gutter);
    scroll-padding-inline:var(--gutter);
  }
  .best__foot{gap:16px;margin-top:clamp(20px,4vw,28px)}
}

/* ---------- just landed — one launch, three arrivals, no second grid ---------- */
.landed{padding-block:var(--space-lg) 0}
.landed__grid{
  display:grid;grid-template-columns:minmax(0,57fr) minmax(0,43fr);
  gap:clamp(18px,2.4vw,40px);align-items:stretch;
}

/* the launch reads as a campaign: one image, copy over a soft gradient */
.launch{display:flex;position:relative}
.launch__media{
  flex:1;position:relative;display:block;overflow:hidden;background:var(--ivory);border-radius:var(--radius-lg);
  min-height:clamp(420px,43vw,620px);
}
.launch__media .pl img{transition:transform 1.4s var(--slow)}
.launch:hover .launch__media .pl img{transform:scale(1.035)}
/* Only the foot is tinted now. The band that used to darken the top read as a
   shadow cast across the block — the same device the hero carried, and it goes
   with it. The copy at the bottom still needs its backing, so that half stays. */
.launch__media::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(24,16,9,0) 0,rgba(24,16,9,0) 52%,
             rgba(24,16,9,.46) 76%,rgba(24,16,9,.72) 100%);
}
.launch__flag{
  position:absolute;z-index:2;top:clamp(14px,1.5vw,24px);left:clamp(14px,1.5vw,24px);
  display:inline-flex;align-items:center;gap:10px;color:var(--on-dark);
  font-size:10px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;
}
.launch__flag::before{content:"";width:26px;height:1px;background:currentColor;opacity:.55}
.launch__body{
  position:absolute;z-index:2;left:0;right:0;bottom:0;color:var(--on-dark);
  padding:clamp(18px,2.1vw,34px);display:grid;gap:7px;
}
.launch__brand{font-size:var(--t-label);letter-spacing:.16em;text-transform:uppercase;opacity:.75}
/* the copy gets roughly two thirds of the banner — the right of the frame stays open */
.launch__t{
  font-family:var(--display);font-weight:300;font-size:clamp(1.7rem,2.5vw,2.6rem);
  line-height:1.04;letter-spacing:-.018em;max-width:66%;text-wrap:balance;
}
.launch__line{font-size:var(--t-meta);opacity:.82;max-width:72%;text-wrap:pretty}
.launch__foot{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  margin-top:clamp(9px,1vw,15px);padding-top:clamp(12px,1.2vw,18px);
  border-top:1px solid rgba(242,237,230,.26);
}
.launch__price{font-size:1.0625rem;font-weight:500;font-variant-numeric:tabular-nums}
.launch__cta{display:inline-flex;align-items:center;gap:10px;font-size:var(--t-label);
  font-weight:500;letter-spacing:var(--ls-ui);text-transform:uppercase}
.launch__cta svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:1.3;
  transition:transform .5s var(--slow)}
.launch:hover .launch__cta svg{transform:translateX(6px)}

/* three arrivals, as rows — deliberately not the card grid above */
.nwlist{display:grid;grid-auto-rows:1fr;align-content:stretch}
.nwc{
  position:relative;display:grid;align-items:center;
  grid-template-columns:clamp(94px,8.4vw,128px) minmax(0,1fr) auto;
  gap:clamp(14px,1.5vw,24px);padding:clamp(10px,1.1vw,16px) 0;
  border-top:1px solid var(--line-soft);
}
.nwlist>.nwc:last-child{border-bottom:1px solid var(--line-soft)}
.nwc__media{position:relative;overflow:hidden;background:var(--ivory);aspect-ratio:4/5;border-radius:var(--radius-md);}
.nwc__media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform 1.1s var(--slow),opacity .55s var(--ease)}
.nwc__media .alt{opacity:0}
.nwc:hover .nwc__media .main{opacity:0;transform:scale(1.04)}
.nwc:hover .nwc__media .alt{opacity:1;transform:scale(1.04)}
.nwc .flags{top:9px;left:9px;gap:4px}
.nwc .flags--deal{left:auto;right:9px}
.nwc .flag{font-size:9px;padding:4px 6px;letter-spacing:.12em}
.nwc__info{display:grid;gap:3px;min-width:0}
.nwc__n{font-size:clamp(.95rem,.3vw + .89rem,1.0625rem);font-weight:500;line-height:1.35;letter-spacing:-.005em}
.nwc__n a{background-image:linear-gradient(currentColor,currentColor);background-size:0 1px;
  background-position:0 100%;background-repeat:no-repeat;transition:background-size .5s var(--slow)}
.nwc:hover .nwc__n a{background-size:100% 1px}
.nwc__row{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-top:5px}
.nwc__act{display:flex;align-items:center;gap:6px}
.nwc__b{
  width:34px;height:34px;display:grid;place-items:center;color:var(--ink-45);
  border:1px solid var(--line-soft);border-radius:50%;
  transition:color .3s var(--ease),border-color .3s var(--ease),background .3s var(--ease);
}
.nwc__b svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.35}
.nwc__b:hover{color:var(--ink);border-color:var(--line)}
.nwc__b--add:hover{background:var(--ink);color:var(--milk);border-color:var(--ink)}
.nwc__b.on{color:var(--accent);border-color:var(--accent-soft)}
.nwc__b.on svg{fill:var(--accent);stroke:var(--accent)}
.nwc__b.done{background:var(--accent);border-color:var(--accent);color:#fff}

@media (max-width:1024px){
  .landed__grid{grid-template-columns:1fr;gap:clamp(22px,3vw,38px)}
  .launch__media{min-height:clamp(360px,54vw,520px)}
  .nwlist{grid-auto-rows:auto}
}
@media (max-width:700px){
  .nwlist{
    display:flex;grid-auto-rows:auto;gap:12px;
    overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding-inline:var(--gutter);
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
    margin-inline:calc(var(--gutter) * -1);padding-inline:var(--gutter);
    padding-block:24px;margin-block:-24px;
  }
  .nwlist::-webkit-scrollbar{display:none}
  /* The desktop row is three columns wide — thumb | copy | buttons. Inside a
     swipe card that leaves the product name about 110px, which breaks a name
     like "Peach 70 Niacin Conditioning Serum" over four lines. The buttons
     drop under the copy instead, so the name gets the whole column. */
  .nwc{
    flex:0 0 min(76vw,330px);scroll-snap-align:start;
    grid-template-columns:clamp(84px,23vw,104px) minmax(0,1fr);
    grid-template-rows:auto auto;align-items:start;
    column-gap:12px;row-gap:10px;
    border:1px solid var(--line-soft);border-top:1px solid var(--line-soft);
    padding:10px 12px 10px 10px;
  }
  /* the thumbnail runs the full height of the copy beside it, so the card has
     no dead strip under a short picture */
  /* aspect-ratio has to go with the stretch: spanning both rows makes the row
     height drive the width through the ratio, and the picture then spills out
     of its column onto the first few pixels of the product name */
  .nwc__media{grid-row:1/span 2;align-self:stretch;aspect-ratio:auto}
  .nwc__info,.nwc__act{grid-column:2}
  .nwlist>.nwc:last-child{border-bottom:1px solid var(--line-soft)}
  /* the last card's start-snap sits past the end of the scroll range, so with
     mandatory snapping the final swipe never lands — it snaps to its end edge */
  .nwlist>.nwc:last-child{scroll-snap-align:end}
  .launch__t,.launch__line{max-width:none}
}

@media (max-width:560px){
  .card__desc{display:none}
  .qadd{transform:none;height:42px;background:transparent;border-top:1px solid var(--line-soft)}
  .wish{opacity:1;transform:none;bottom:52px;right:8px;width:32px;height:32px}
  .flags{top:11px;left:11px}
  .flags--deal{right:11px}
}

.card__link{position:absolute;inset:0;z-index:1;display:block}
.card__name a{background-image:linear-gradient(currentColor,currentColor);background-size:0 1px;
  background-position:0 100%;background-repeat:no-repeat;transition:background-size .5s var(--slow)}
.card:hover .card__name a{background-size:100% 1px}
