/* ═══════════════════════════════════════════════════════════════════
   Gazillion — product display page
   Standalone HTML / CSS / JS. No framework, no build step, no CDN.

   Typeface is Futura, delivered as Jost (the open-source revival already
   running on gazillion.in), inlined in font.css so file:// renders true.

   Colour: wherever the reference layout runs navy, this runs Gazillion's
   bronze. Two tones, and the split is not cosmetic —
     --brand  #7d6b52  luminance .155 → 5.12:1 on white. Carries white text.
     --bronze #998468  luminance .243 → 3.59:1 on white. Fails AA on small
                       text, so it is only ever a rule, a hover or a mark.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  /* ground */
  --paper:#ffffff;
  --panel:#f7f5f2;        /* faintly warm, biased toward the bronze */
  --stone:#ece7e0;

  /* brand */
  --brand:#7d6b52;        /* fills, buttons, the announcement band */
  --brand-dk:#645440;     /* pressed / hover on a brand fill */
  --bronze:#998468;       /* the wordmark hue — accents only */

  /* ink */
  --ink:#1a1a1a;
  --ink-soft:#5c5c5c;
  --ink-mute:#8a8279;

  /* lines */
  --line:#e6e2dc;
  --line-2:#cfc7bb;

  /* signals */
  --sale:#9e2a2b;
  --ok:#3f6b52;

  --font:'Jost','Futura','Futura PT','Century Gothic',system-ui,sans-serif;

  /* metrics */
  --maxw:1800px;
  --gut:clamp(16px,1.6vw,28px);
  --anno-h:38px;
  --hdr-h:62px;
  --pad:clamp(20px,6.6vw,105px);  /* the buy panel's symmetric inset */
  --sec:clamp(52px,7vw,120px);    /* air between one section and the next */

  --shot:2 / 3;                   /* the ratio every gallery cell is cropped to */
  --r:2px;
  --ease:cubic-bezier(.4,.1,.25,1);
}

/* ── reset ─────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--font);font-size:14px;line-height:1.55;
  font-weight:300;letter-spacing:.01em;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img{display:block;max-width:100%;height:auto}
h1,h2,h3,p,ul,figure{margin:0}
ul{padding:0;list-style:none}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
svg{fill:none;stroke:currentColor;stroke-width:1.35;stroke-linecap:round;stroke-linejoin:round}
s{text-decoration-thickness:1px}

:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:var(--r)}

.skip{
  position:fixed;top:8px;left:8px;z-index:200;
  padding:10px 16px;background:var(--brand);color:#fff;
  font-size:12px;letter-spacing:.08em;text-transform:uppercase;
  transform:translateY(-160%);transition:transform .18s var(--ease);
}
.skip:focus{transform:none}

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

/* ── announcement ──────────────────────────────────────────────── */
.anno{
  position:relative;background:var(--brand);color:#fff;
  min-height:var(--anno-h);display:flex;align-items:center;justify-content:center;
  padding:9px 46px;text-align:center;
}
.anno p{font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;font-weight:300}
.anno strong{font-weight:500}
/* The two qualifying phrases. They carry the full sentence on a wide screen
   and drop out on a phone so the band stays one line, as the reference does. */
.anno__wide{display:inline}
.anno a{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.anno a:hover{opacity:.8}
.anno__x{position:absolute;right:12px;top:50%;translate:0 -50%;padding:6px;opacity:.75}
.anno__x:hover{opacity:1}
.anno__x svg{width:15px;height:15px}
.anno.is-gone{display:none}

/* ── header ────────────────────────────────────────────────────
   The height is FIXED at --hdr-h, not min-height, and the nav is told never
   to wrap. That is not tidiness: the sticky product bar is pinned at
   top:var(--hdr-h), so the moment the nav wrapped to a second line the header
   grew past its own token and swallowed the top of the bar — which is why the
   bar appeared to be sitting behind the header on the way back up. One
   authoritative height, and the two can no longer overlap. */
/* The header does not ride the whole page down. Scroll down and it lifts out
   of the way; scroll back up — at any point, at any speed — and it drops
   straight back in. Only the product bar is permanently pinned. The state
   lives on <body> because the sticky bar has to react to it too: with the
   header gone there is nothing above it, so it reclaims top:0. */
.hdr{
  position:sticky;top:0;z-index:60;background:var(--paper);border-bottom:1px solid var(--line);
  transition:translate .3s var(--ease);
}
body.is-hdr-off .hdr{translate:0 -100%}
.hdr__in{
  max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gut);
  height:var(--hdr-h);
  display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:24px;
}
.hdr__burger{display:none}
.hdr__burger svg{width:22px;height:22px}
.hdr__logo img{width:clamp(112px,9vw,150px);height:auto}

.hdr__nav{display:flex;justify-content:center;gap:clamp(14px,1.7vw,30px);flex-wrap:nowrap;white-space:nowrap}
.hdr__nav a{
  position:relative;padding:6px 0;
  font-size:11.5px;font-weight:400;letter-spacing:.115em;text-transform:uppercase;
  color:var(--ink);
}
.hdr__nav a::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--brand);scale:0 1;transform-origin:left;
  transition:scale .22s var(--ease);
}
.hdr__nav a:hover::after,.hdr__nav a[aria-current]::after{scale:1 1}
.hdr__sale{color:var(--sale)!important}

.hdr__ico{display:flex;align-items:center;gap:clamp(8px,1vw,16px);justify-self:end}
.hdr__ico button{padding:7px;color:var(--ink)}
.hdr__ico button:hover{color:var(--brand)}
.hdr__ico svg{width:20px;height:20px}
.hdr__bag{position:relative}
.hdr__n{
  position:absolute;top:1px;right:0;min-width:16px;height:16px;padding:0 4px;
  display:grid;place-items:center;border-radius:999px;
  background:var(--brand);color:#fff;
  font-size:9.5px;font-weight:500;line-height:1;font-variant-numeric:tabular-nums;
}
.hdr__n[hidden]{display:none}
/* Account and wishlist duplicate what the drawer already offers on a phone,
   and four icons crowd the bag out at 360px. */
.is-hide-sm{display:inline-flex}

.mnav{display:none;flex-direction:column;border-top:1px solid var(--line);padding:6px var(--gut) 14px}
.mnav a{
  padding:13px 0;border-bottom:1px solid var(--line);
  font-size:13px;letter-spacing:.09em;text-transform:uppercase;
}
.mnav a:last-child{border-bottom:0}
.mnav.is-open{display:flex}

/* ═══════════════ PDP ═══════════════
   Two columns, unequal, and deliberately not partners. The gallery is a
   grid child with no gutter on its outer edge, so photographs start at
   x=0. The right column is an ordinary column that runs out — align-items
   start is what lets the pictures carry on alone below it. */
.pdp{
  display:grid;
  grid-template-columns:minmax(0,57fr) minmax(0,43fr);
  align-items:start;
}

/* ── gallery ───────────────────────────────────────────────────── */
.gal{position:relative;min-width:0}
.gal__track{display:grid;grid-template-columns:1fr 1fr;gap:2px}
/* width:100% is load-bearing, not belt-and-braces. A grid item that carries
   BOTH a preferred aspect-ratio and a constraining max-height loses stretch
   alignment in the inline axis — the ratio starts driving the width, and the
   figure shrinks to roughly two thirds of its track, leaving the dead white
   band down the right of the gallery. A definite width takes the ratio out of
   that negotiation: width fills the track, max-height caps the height, and
   object-fit:cover absorbs the difference. */
/* zoom-in is the affordance doing the real work: the cursor changes the moment
   the pointer crosses any photograph, so the whole frame reads as clickable
   before the shopper has to find a 38px mark in a corner. */
.gal__f{position:relative;margin:0;width:100%;overflow:hidden;background:var(--panel);aspect-ratio:var(--shot);cursor:zoom-in}
/* A full-width frame at the source ratio is ~1.5x the width — on a 57%
   column that is taller than any monitor, and the first thing a shopper
   would see is a headless midriff. Capping to the window keeps the whole
   garment on the opening screen; the half frames are short enough already. */
.gal__f--full{grid-column:span 2;max-height:calc(100vh - var(--hdr-h) - 8px)}
.gal__f--half{grid-column:span 1}
.gal__f img{width:100%;height:100%;object-fit:cover;object-position:50% 22%}

/* The zoom mark top-right, and on the first frame, the pill that jumps to
   Complete the look. Both are keyboard-reachable, so they also show on
   :focus-visible.

   The mark now rests at .55 rather than at 0. A control that exists only
   after you happen to hover the right rectangle is a control most people
   never learn is there — and a shopper who cannot find the full-screen
   gallery assumes the page does not have one. At .55 over a photograph it
   is quiet enough not to add six badges of clutter to the column, and
   present enough to be an answer to "can I see this bigger". */
.gal__zoom{
  position:absolute;top:14px;right:14px;z-index:2;
  width:38px;height:38px;display:grid;place-items:center;
  background:rgba(255,255,255,.94);color:var(--ink);
  border-radius:50%;box-shadow:0 1px 6px rgba(0,0,0,.1);
  opacity:.55;transition:opacity .18s var(--ease),scale .18s var(--ease);
}
.gal__zoom svg{width:16px;height:16px;stroke-width:1.5}
.gal__f:hover .gal__zoom,.gal__zoom:focus-visible{opacity:1}
.gal__zoom:active{scale:.92}
.gal__zoom:hover{background:#fff;color:var(--brand)}

.gal__ctl{
  position:absolute;left:20px;bottom:auto;top:var(--pill-y,60vh);z-index:3;
  display:inline-flex;align-items:center;gap:9px;
  padding:12px 20px;background:rgba(255,255,255,.94);color:var(--ink);
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;font-weight:400;
  box-shadow:0 1px 8px rgba(0,0,0,.1);
  opacity:0;pointer-events:none;transition:opacity .2s var(--ease);
}
.gal__ctl svg{width:14px;height:14px}
.gal:hover .gal__ctl,.gal__ctl:focus-visible{opacity:1;pointer-events:auto}
.gal__ctl:hover{background:#fff;color:var(--brand)}

/* Carousel furniture — phone only, hidden here. */
.gal__count,.gal__expand{display:none}

/* ── buy panel ─────────────────────────────────────────────────── */
.buy{
  min-width:0;
  padding:clamp(26px,3vw,46px) var(--pad) clamp(40px,5vw,80px);
}

.crumb{
  display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  font-size:11px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-mute);margin-bottom:clamp(18px,2.2vw,30px);
}
.crumb a:hover{color:var(--brand)}
.crumb span[aria-current]{color:var(--ink-soft)}

.buy__head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}
.buy__name{
  font-size:clamp(21px,1.5vw,27px);font-weight:400;line-height:1.22;
  letter-spacing:.005em;text-wrap:balance;
}
.wish{padding:5px;color:var(--ink-soft);flex:0 0 auto}
.wish svg{width:21px;height:21px}
.wish:hover{color:var(--brand)}
.wish[aria-pressed="true"]{color:var(--sale)}
.wish[aria-pressed="true"] svg{fill:currentColor}

.buy__vendor{
  margin-top:7px;font-size:11px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--bronze);font-weight:400;
}

.buy__price{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-top:clamp(14px,1.6vw,22px)}
.buy__amt{font-size:16px;font-weight:500;letter-spacing:.02em;font-variant-numeric:tabular-nums}
.buy__was{font-size:13.5px;color:var(--ink-mute);font-variant-numeric:tabular-nums}
.buy__off{
  font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;font-weight:500;
  color:var(--sale);border:1px solid currentColor;padding:2px 7px;
}
.buy__mrp{margin-top:5px;font-size:11px;letter-spacing:.04em;color:var(--ink-mute)}

/* options */
.opt{margin-top:clamp(20px,2.4vw,32px)}
.opt__row{display:flex;align-items:center;justify-content:space-between;gap:14px}
.opt__lbl{
  font-size:11.5px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-soft);
}
.opt__lbl strong{font-weight:400;color:var(--ink);margin-left:7px;letter-spacing:.05em}
.opt__hint{margin-top:11px;font-size:11.5px;letter-spacing:.03em;color:var(--ink-mute)}
.opt__hint.is-warn{color:var(--sale)}

.link-sm{
  font-size:11.5px;letter-spacing:.04em;color:var(--ink-soft);
  text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--line-2);
}
.link-sm:hover{color:var(--brand);text-decoration-color:var(--brand)}
/* Same link with a glyph in front of it — the icon sits outside the underline
   so only the words read as the link, the way the reference sets Size chart. */
.link-ico{display:inline-flex;align-items:center;gap:7px;text-decoration:none}
.link-ico span{text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--line-2)}
.link-ico:hover span{text-decoration-color:var(--brand)}
.link-ico svg{width:17px;height:12px;flex:0 0 17px;stroke-width:1.3}

.sw{display:flex;gap:9px;margin-top:11px}
/* The chip carries a crop of the cloth, not a flat disc of dye. What is being
   chosen is a woven cotton twill, and the weave and the way the colour sits
   in it are most of what the customer is judging — a paint dot throws that
   away and reads as a spec sheet.

   The source is a square already cropped to the weave, so the position is a
   plain 50% 50%. It used to be 55% down a full-length portrait, which is the
   whole reason the chip showed a small photograph of a person: `cover` on a
   34px circle can only ever frame a 34px-wide slice of whatever it is given,
   and given a person it frames the person.

   --sw stays underneath as the ground: the shorthand paints the colour first
   and the crop over it, so a chip whose image is slow or blocked is still
   Scarlet Red rather than a grey hole. It is set slightly larger than a flat
   chip would be, because a texture needs a little room to read as one. */
.sw__b{
  width:34px;height:34px;border-radius:50%;
  background:var(--sw,#ccc) var(--sw-img,none) 50% 50% / cover no-repeat;
  box-shadow:0 0 0 1px rgba(0,0,0,.14) inset;
  outline-offset:3px;
}
.sw__b.is-on{outline:1px solid var(--ink)}

.sizes{display:flex;flex-wrap:wrap;gap:7px;margin-top:11px}
.size{
  min-width:52px;min-height:42px;padding:0 12px;
  border:1px solid var(--line-2);background:var(--paper);
  font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;
  transition:border-color .15s var(--ease),background .15s var(--ease);
}
.size:hover{border-color:var(--ink)}
.size.is-on{background:var(--ink);border-color:var(--ink);color:#fff}
.size[data-avail="0"]{
  color:var(--ink-mute);border-color:var(--line);cursor:not-allowed;
  background:linear-gradient(to top left,transparent calc(50% - .5px),var(--line) 50%,transparent calc(50% + .5px));
}

.atc{margin-top:clamp(20px,2.4vw,30px)}

.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 22px;
  font-size:12px;font-weight:400;letter-spacing:.18em;text-transform:uppercase;
  border:1px solid transparent;transition:background .16s var(--ease),color .16s var(--ease);
}
.btn--brand{width:100%;min-height:54px;background:var(--brand);color:#fff}
.btn--brand:hover{background:var(--brand-dk)}
.btn--ghost-light{border-color:rgba(255,255,255,.75);color:#fff;min-height:46px;letter-spacing:.15em}
.btn--ghost-light:hover{background:#fff;color:var(--ink)}
/* Terminal actions — checkout, submit. Near-black rather than bronze, so the
   one bronze button on the page stays the one that adds the garment. */
.btn--dark{background:var(--ink);color:#fff}
.btn--dark:hover{background:#000}
.btn--out{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn--out:hover{background:var(--ink);color:#fff}

/* Enough air that Add to bag reads as the end of the transaction, not one
   item in a list — but not the chasm it was. The reference leaves about a
   line and a half; a full thumb's height of nothing just looked broken. */
.desc{margin-top:clamp(20px,2.4vw,32px)}
.desc p{font-size:14px;line-height:1.72;color:var(--ink-soft);letter-spacing:.005em}

/* ── inline plates, phone only ──────────────────────────────
   Held at display:none so a desktop browser never fetches either file. */
.inl{display:none}

/* ── accordions ────────────────────────────────────────────────
   Icon, uppercase label, arrow. Hairlines only — this is what replaces
   the boxed delivery / returns / COD panel that used to sit here. */
.acc{margin-top:clamp(22px,2.6vw,34px);border-top:1px solid var(--line)}
.acc__i{border-bottom:1px solid var(--line)}
.acc__b{
  display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:14px;
  width:100%;padding:18px 2px;text-align:left;
}
.acc__ico{width:19px;height:19px;flex:0 0 19px;color:var(--bronze);stroke-width:1.3}
.acc__t{font-size:12px;font-weight:500;letter-spacing:.12em;text-transform:uppercase}
.acc__ar{width:19px;height:19px;color:var(--ink-soft);transition:translate .2s var(--ease)}
.acc__b:hover .acc__ar{translate:3px 0;color:var(--brand)}
.acc__b:hover .acc__ico{color:var(--brand)}

/* The four content blocks. They never render in place — the panel lifts
   their innards on open — but they stay in the document as the single
   source of the words, and the rules below dress them once the panel has
   adopted them (.dlg__b re-uses these selectors verbatim). */
.acc__p{padding:0 2px 20px}
.acc__p p{font-size:13px;line-height:1.72;color:var(--ink-soft)}
.acc__p p + p{margin-top:11px}
.acc__p ul{display:grid;gap:8px}
.acc__p li{
  position:relative;padding-left:16px;font-size:13px;line-height:1.6;color:var(--ink-soft);
}
.acc__p li::before{
  content:"";position:absolute;left:0;top:.62em;width:6px;height:1px;background:var(--bronze);
}
.acc__p a{text-decoration:underline;text-underline-offset:3px;color:var(--brand)}
.acc__meta{margin-top:14px;font-size:11px;letter-spacing:.05em;color:var(--ink-mute)}
.acc__note{font-size:12px!important;color:var(--ink-mute)!important}
.acc__warn{
  margin-top:12px!important;padding:10px 12px;background:var(--panel);
  border-left:2px solid var(--sale);font-size:12.5px!important;
}

/* ── complete the look ─────────────────────────────────────────
   Last child of the right column. Three rows, image left, copy right —
   the horizontal card keeps the block short enough that the column still
   ends well above the last photograph. */
.ctl{margin-top:clamp(34px,4vw,54px);padding-top:clamp(24px,2.6vw,34px);border-top:1px solid var(--line)}
.ctl__top{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  margin-bottom:clamp(16px,1.8vw,24px);
}
.ctl__h{font-size:19px;font-weight:400;letter-spacing:.02em}
.ctl__list{display:block}
/* All three on screen at once — no arrows. The thumbnail is the size it is
   on purpose: at 96px these read as a footnote to the shirt; at ~200 they
   read as things you could actually buy, which is the whole point of the
   block. */
.ctl__i{
  display:grid;grid-template-columns:clamp(148px,17vw,205px) minmax(0,1fr);
  gap:clamp(16px,1.6vw,24px);align-items:center;padding:clamp(14px,1.5vw,18px) 0;
}
.ctl__i + .ctl__i{border-top:1px solid var(--line)}
.ctl__img{background:var(--panel);overflow:hidden}
.ctl__img img{
  width:100%;aspect-ratio:4 / 5;object-fit:cover;object-position:50% 30%;
  transition:scale .4s var(--ease);
}
.ctl__i:hover .ctl__img img{scale:1.04}
.ctl__v{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--bronze)}
.ctl__b h3{margin-top:5px;font-size:13.5px;font-weight:400;line-height:1.38;letter-spacing:.02em}
.ctl__b h3 a:hover{color:var(--brand)}
.ctl__p{margin-top:6px;font-size:12.5px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.ctl__p s{color:var(--ink-mute);margin-left:5px;font-size:11px}

.quick{
  display:inline-flex;align-items:center;gap:7px;margin-top:9px;
  padding:7px 13px;border:1px solid var(--line-2);
  font-size:10px;letter-spacing:.13em;text-transform:uppercase;
  transition:border-color .15s var(--ease),background .15s var(--ease),color .15s var(--ease);
}
.quick svg{width:13px;height:13px;stroke-width:1.3}
.quick:hover{background:var(--brand);border-color:var(--brand);color:#fff}

/* ═══════════════ WHY YOU WILL LOVE THIS ONE ═══════════════
   Gazillion's own section, lifted from the live Gracy page and given the
   words back. On their site the three sentences are baked into the
   photographs — which means nobody on a screen reader, and nobody whose
   images have not arrived, ever gets them. Here the picture is the picture
   and the sentence is text.

   It sits on the warm panel so the change of ground does the separating and
   the eye reads it as a new chapter rather than more of the product page. */
/* --d is the per-card stagger; script overwrites it on each card. The default
   here is what keeps the calc() in the rules below valid before it does. */
.love{--d:0s;background:var(--panel);border-top:1px solid var(--line)}
.love__in{max-width:var(--maxw);margin-inline:auto;padding:var(--sec) var(--gut)}
.love__eyebrow{
  text-align:center;font-size:11px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--bronze);
}
.love__h{
  margin-top:12px;text-align:center;text-wrap:balance;
  font-size:clamp(22px,2.4vw,38px);font-weight:300;line-height:1.16;letter-spacing:.005em;
}
.love__grid{
  margin-top:clamp(28px,3.4vw,58px);
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(16px,2.2vw,42px);
}
.love__i{min-width:0}
.love__img{position:relative;overflow:hidden;background:var(--stone)}
.love__img img{width:100%;aspect-ratio:3 / 4;object-fit:cover;transition:scale .5s var(--ease)}
.love__i:hover .love__img img{scale:1.04}
/* Icon spans both text rows so the heading and the sentence hang off one
   optical left edge instead of two. */
.love__b{
  margin-top:clamp(14px,1.5vw,22px);
  display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:14px;row-gap:6px;align-items:start;
}
.love__ico{
  grid-row:span 2;align-self:start;
  width:40px;height:40px;display:grid;place-items:center;
  border:1px solid var(--line-2);border-radius:50%;
  color:var(--brand);background:var(--paper);
  transition:border-color .3s var(--ease),background .3s var(--ease),color .3s var(--ease);
}
.love__ico svg{
  width:20px;height:20px;stroke-width:1.25;
  transition:rotate .45s var(--ease),scale .45s var(--ease);
}
.love__i:hover .love__ico{border-color:var(--brand);background:var(--brand);color:#fff}
.love__i:hover .love__ico svg{rotate:-8deg;scale:1.08}
.love__b h3{
  position:relative;align-self:center;padding-bottom:9px;
  font-size:14px;font-weight:500;letter-spacing:.05em;
}
/* A bronze rule that draws itself out from under the heading as the card
   arrives — the one piece of decoration in the section, and it only ever
   happens once per card. */
.love__b h3::after{
  content:"";position:absolute;left:0;bottom:0;width:34px;height:1px;
  background:var(--bronze);transform-origin:left;
  transition:scale .55s var(--ease) calc(var(--d) + .34s);
}
/* Collapsed only once script has armed the section — with JS off the rule
   is simply drawn, never a permanently invisible decoration. */
.love.reveal .love__b h3::after{scale:0 1}
.love__b p{font-size:13px;line-height:1.68;color:var(--ink-soft)}

/* ── arrival ───────────────────────────────────────────────────
   The .reveal class is added by script, never by the markup: with JavaScript
   off nothing is ever hidden, so the section reads exactly as it does now.
   Each card carries its own --d, so they land left to right rather than all
   at once — a beat of choreography, not a light show. */
.love.reveal .love__eyebrow,
.love.reveal .love__h,
.love.reveal .love__i{
  opacity:0;translate:0 20px;
  transition:opacity .62s var(--ease) var(--d),translate .62s var(--ease) var(--d);
}
.love.reveal .is-in{opacity:1;translate:0 0}
/* The curtain over each photograph, lifting from the top. */
.love.reveal .love__img::after{
  content:"";position:absolute;inset:0;background:var(--panel);
  transform-origin:top;scale:1 1;
  transition:scale .72s var(--ease) calc(var(--d) + .1s);
}
.love.reveal .love__i.is-in .love__img::after{scale:1 0}
.love.reveal .love__i.is-in .love__b h3::after{scale:1 1}

/* ═══════════════ YOU MAY ALSO LIKE ═══════════════
   --agap is declared on the section, not inline in the track, because the
   column width is computed from it. */
.also{
  --agap:clamp(10px,1.2vw,20px);
  max-width:var(--maxw);margin-inline:auto;
  padding:var(--sec) var(--gut) clamp(30px,3.5vw,56px);
}
/* Arrows first, heading second — the control belongs beside the words it
   scrolls, not thrown to the opposite end of an 1800px row. */
.also__top{display:flex;align-items:center;justify-content:flex-start;gap:clamp(12px,1.2vw,20px);margin-bottom:clamp(18px,2vw,28px)}
.also__top h2{font-size:clamp(18px,1.35vw,23px);font-weight:400;letter-spacing:.02em}

/* ── pill ──────────────────────────────────────────────────────
   Two bare hairline circles, not a filled capsule — shared by both
   carousels so they cannot drift apart. */
.pill{display:inline-flex;align-items:center;gap:8px;flex:0 0 auto}
.pill__b{
  width:36px;height:36px;display:grid;place-items:center;border-radius:50%;
  border:1px solid var(--line-2);color:var(--ink);
  transition:background .15s var(--ease),color .15s var(--ease),border-color .15s var(--ease),opacity .15s var(--ease);
}
.pill__b:hover:not(:disabled){background:var(--ink);border-color:var(--ink);color:#fff}
.pill__b:disabled{opacity:.28;cursor:default}
.pill__b svg{width:15px;height:15px}

/* Four cards on screen and the fifth off the right edge. The track size is
   DEFINITE on purpose. minmax(0,1fr) let five cards squeeze into whatever
   width was going, so the row never overflowed, the arrows had nothing to
   scroll, and on a phone the same five crushed to a fifth of the screen
   each. A fixed fraction of the container is what makes it a carousel. */
.also__row{
  display:grid;grid-auto-flow:column;
  grid-auto-columns:calc((100% - 3 * var(--agap)) / 4);
  gap:var(--agap);
  overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;scroll-behavior:smooth;
}
.also__row::-webkit-scrollbar{display:none}
.card{scroll-snap-align:start;min-width:0}
.card img{
  width:100%;aspect-ratio:var(--shot);object-fit:cover;object-position:50% 20%;
  background:var(--panel);transition:opacity .25s var(--ease);
}
.card a:hover img{opacity:.88}
.card__v{margin-top:12px;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--bronze)}
.card__n{margin-top:5px;font-size:13px;font-weight:400;line-height:1.4}
.card a:hover .card__n{color:var(--brand)}
.card__p{margin-top:4px;font-size:12px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.card__p s{color:var(--ink-mute);margin-left:5px;font-size:11px}

/* ═══════════════ RECENTLY VIEWED ═══════════════
   The heading is not above the row, it is beside it — two words stacked
   large on the left with the cards running off the right edge of the
   window. That asymmetry is the whole shape of the section; keep it.

   --rvgap is declared on the section rather than inline in the track
   because the auto-column width is computed from it. */
.rv{
  --rvgap:clamp(10px,1.1vw,18px);
  max-width:var(--maxw);margin-inline:auto;
  padding:var(--sec) var(--gut);
  display:grid;grid-template-columns:minmax(0,clamp(200px,20vw,290px)) minmax(0,1fr);
  gap:clamp(24px,3vw,58px);align-items:start;
}
.rv__h{
  display:flex;flex-direction:column;
  font-size:clamp(30px,3.5vw,56px);font-weight:300;line-height:1.02;letter-spacing:-.012em;
}
.rv__h span:last-child{color:var(--bronze)}
.rv__note{
  margin-top:clamp(14px,1.6vw,22px);max-width:32ch;
  font-size:12.5px;line-height:1.7;color:var(--ink-soft);
}
.pill--rv{margin-top:clamp(18px,2vw,30px)}

.rv__wrap{position:relative;min-width:0}
.rv__row{
  display:grid;grid-auto-flow:column;
  grid-auto-columns:calc((100% - 2 * var(--rvgap)) / 3);
  gap:var(--rvgap);
  overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;scroll-behavior:smooth;
}
.rv__row::-webkit-scrollbar{display:none}
.card--rv img{object-position:50% 30%}

/* Circular paddles over the photographs, not beside them. --pad-y is written
   by the script from the real height of the first picture, because the cards
   carry text under the image and no CSS percentage can find the middle of
   just the picture. */
.rv__pad{
  position:absolute;top:var(--pad-y,34%);translate:0 -50%;z-index:3;
  width:46px;height:46px;display:grid;place-items:center;border-radius:50%;
  background:rgba(255,255,255,.94);color:var(--ink);
  box-shadow:0 1px 10px rgba(0,0,0,.14);
  transition:background .16s var(--ease),color .16s var(--ease),opacity .16s var(--ease);
}
.rv__pad svg{width:18px;height:18px}
.rv__pad:hover{background:#fff;color:var(--brand)}
.rv__pad:disabled{opacity:0;pointer-events:none}
.rv__pad--prev{left:-16px}
.rv__pad--next{right:-16px}

/* ═══════════════ CAMPAIGN BAND ═══════════════ */
.band{position:relative;isolation:isolate}
.band img{width:100%;height:clamp(300px,42vw,560px);object-fit:cover;object-position:50% 30%}
.band::after{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(90deg,rgba(20,16,10,.52) 0%,rgba(20,16,10,.26) 46%,rgba(20,16,10,0) 74%);
}
.band__in{
  position:absolute;z-index:2;inset:0;
  display:flex;flex-direction:column;justify-content:center;align-items:flex-start;gap:16px;
  max-width:var(--maxw);margin-inline:auto;padding-inline:clamp(24px,5vw,86px);
  color:#fff;
}
.band__eyebrow{font-size:11px;letter-spacing:.22em;text-transform:uppercase;opacity:.9}
.band__h{font-size:clamp(24px,2.6vw,42px);font-weight:300;line-height:1.14;max-width:14ch;text-wrap:balance}
.band__cta{display:flex;gap:10px;flex-wrap:wrap;margin-top:4px}

/* ═══════════════ FOOTER ═══════════════
   Light, ruled, four columns. Rules run the full width of the window while
   the content stays inside the shell. */
.foot{border-top:1px solid var(--line);background:var(--paper)}

/* ── from the journal ──────────────────────────────────────────
   Two articles, sitting directly above the social tiles. Two and not three:
   the store's blog sitemap holds exactly three entries and the third is an
   unfinished placeholder with no image.

   This is a shelf in a footer, not a blog index, so it is set at footer
   scale — a small square thumbnail, a kicker, a title, a link — on the same
   paper as the columns above it rather than on a panel of its own, with one
   hairline separating it from them. The heading sits in the column-title
   style for the same reason: the footer should read as one system, not as a
   footer with a magazine bolted underneath it.

   The excerpt is dropped rather than shrunk. Two lines of body copy beside
   an 84px thumbnail turn a tidy row into a wall, and the title of an
   article called "All about the white shirt" is already the summary. */
.jour{border-top:1px solid var(--line)}
.jour .shell{padding-block:clamp(24px,3vw,40px)}
/* The heading and the link sit together in the middle rather than pushed to
   opposite ends, because the two articles below them are centred now — a
   title hard against the left edge above a centred block reads as a mistake. */
.jour__top{display:flex;align-items:center;justify-content:center;gap:clamp(14px,2vw,26px);margin-bottom:clamp(15px,1.6vw,22px)}
.jour__h{font-size:11px;font-weight:500;letter-spacing:.14em;text-transform:uppercase}
.jour__all{
  display:inline-flex;align-items:center;gap:8px;flex:0 0 auto;
  font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-mute);
}
.jour__all svg{width:14px;height:14px;transition:translate .18s var(--ease)}
.jour__all:hover{color:var(--brand)}
.jour__all:hover svg{translate:4px 0}

/* Three topics, the two articles, three more topics — as ONE block, capped
   and centred, not spread across the whole shell.

   The cap is the fix. Sizing the middle track to its content and letting two
   `1fr` sides split the remainder does centre the pair, but on a 1900px
   screen those sides grow to 400px each and fling the tags into the far
   corners, where they stop reading as lists attached to anything and start
   reading as loose words. Capping the band and reversing the tracks — content
   width for the tag stacks, everything left for the articles — keeps the
   three groups close enough to be one composition at any width. */
.jour__band{
  width:min(1040px,100%);margin-inline:auto;
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:stretch;
}
.jour__row{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(20px,2.6vw,38px);padding-inline:clamp(18px,2.2vw,34px);
}
/* Divided by the same full-height hairlines the footer columns above use,
   which is what the dashes were badly imitating: a rule between two groups
   states the relationship, a dash floating beside a word points at nothing.
   align-items:stretch on the band makes the rules span the row rather than
   just the height of three short lines.

   The tags are quieter than the article kickers beside them on purpose — at
   equal weight five stacks of small caps all shout at once, which was the
   other half of the clutter. */
.jour__tags{display:grid;align-content:center;gap:12px;min-width:0}
.jour__tags li{
  font-size:9.5px;line-height:1.2;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-mute);white-space:nowrap;
}
.jour__band > .jour__tags:first-child{
  justify-items:end;text-align:right;
  padding-right:clamp(18px,2.2vw,34px);border-right:1px solid var(--line);
}
.jour__band > .jour__tags:last-child{
  padding-left:clamp(18px,2.2vw,34px);border-left:1px solid var(--line);
}

.jart a{display:grid;grid-template-columns:84px minmax(0,1fr);gap:16px;align-items:center}
.jart__img{display:block;overflow:hidden;background:var(--stone)}
.jart__img img{width:100%;aspect-ratio:1 / 1;object-fit:cover;transition:scale .45s var(--ease)}
.jart a:hover .jart__img img{scale:1.06}
.jart__b{display:block;min-width:0}
.jart__k{display:block;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--bronze)}
.jart__n{margin-top:6px;font-size:13.5px;font-weight:400;line-height:1.32;letter-spacing:.01em}
/* The whole card is the link, so the title carries the affordance itself. The
   underlined "READ THE ARTICLE" that used to sit here was a third line of
   small caps under a title that already links to the same place — the single
   biggest contributor to the clutter, and it said nothing the title didn't. */
.jart a:hover .jart__n{color:var(--brand);text-decoration:underline;text-underline-offset:3px}
.jart__x{display:none}

/* Four columns divided by hairline rules, the way the reference sets them: the
   rule belongs to the column, drawn on its left edge, so the first column has
   none and the count is always one fewer than the columns. Padding-inline gives
   the words clearance from the rule instead of the gap doing all the work. */
.foot__cols{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr)) minmax(0,1.5fr);
  padding-block:clamp(34px,4vw,60px);
}
.foot__c{padding-inline:clamp(16px,2.4vw,44px)}
.foot__c:first-child{padding-left:0}
.foot__c:last-child{padding-right:0}
.foot__c + .foot__c{border-left:1px solid var(--line)}
.foot__t{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;
  font-size:11px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  padding:0 0 16px;cursor:default;
}
.foot__t svg{display:none;width:16px;height:16px}
.foot__p{display:grid;gap:11px}
.foot__p a{font-size:12.5px;color:var(--ink-soft);letter-spacing:.015em;width:fit-content}
.foot__p a:hover{color:var(--brand);text-decoration:underline;text-underline-offset:3px}

/* There is no heading above this column, because the reference has none: the
   consent line is the heading. It is therefore set at the weight and tracking
   of the column titles beside it — so the four columns still start on one
   line — but in full sentences at a readable measure rather than as a label.
   The caps come from the transform, not from typed capitals, so assistive
   technology receives ordinary sentence case. */
.foot__consent{
  font-size:11px;font-weight:500;line-height:1.85;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink);max-width:44ch;
}
/* Input and SUBMIT are butted together — one shared hairline, not two edges a
   gap apart. The -1px pulls the button over the input's own border. */
.foot__f{display:flex;gap:0;margin-top:16px}
.foot__f input{
  flex:1 1 auto;min-width:0;min-height:46px;padding:0 14px;
  border:1px solid var(--line-2);background:var(--paper);
  font:inherit;font-size:13px;color:var(--ink);
}
.foot__f input::placeholder{color:var(--ink-mute)}
.foot__f input:focus-visible{outline:1px solid var(--brand);outline-offset:0;border-color:var(--brand);position:relative;z-index:1}
.foot__f .btn{width:auto;flex:0 0 auto;min-height:46px;padding:0 30px;margin-left:-1px}
.foot__fine{margin-top:12px;font-size:11px;line-height:1.6;color:var(--ink-mute);max-width:46ch}
.foot__fine a{text-decoration:underline;text-underline-offset:2px}
.foot__fine a:hover{color:var(--brand)}

/* Social band: a full-width rule above and below, tiles centred between them.
   Square, not circular — the reference uses hard corners here — and solid
   rather than outlined. At 34px an outline reads as an empty box with
   something small inside it; a filled tile reads as a mark. The fill is the
   brand bronze standing in for the reference's navy, and it carries white
   glyphs at 5.12:1. */
.foot__band{border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.foot__band .shell{display:flex;justify-content:center;padding-block:clamp(18px,2vw,26px)}
.foot__soc{display:flex;gap:8px}
.foot__soc a{
  width:34px;height:34px;display:grid;place-items:center;
  background:var(--brand);color:#fff;
  transition:background .18s var(--ease);
}
.foot__soc a:hover{background:var(--ink)}
.foot__soc svg{width:16px;height:16px}
.foot__guides{display:flex;justify-content:center;gap:clamp(14px,2vw,34px);flex-wrap:wrap}
.foot__guides a{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-soft)}
.foot__guides a:hover{color:var(--brand)}

.foot__base .shell{
  display:flex;flex-direction:column;align-items:center;gap:14px;
  padding-block:clamp(20px,2.4vw,30px);text-align:center;
}
.pay__list{display:flex;justify-content:center;gap:7px;flex-wrap:wrap}
.pay__list li{
  padding:5px 10px;border:1px solid var(--line);
  font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-mute);
}
.foot__copy{font-size:11px;letter-spacing:.04em;color:var(--ink-mute)}

/* ═══════════════ STICKY ADD TO BAG ═══════════════
   Desktop: drops in under the header once the real button is gone. The
   button takes the full height of the bar and bleeds into the right edge —
   no gutter, no margin, exactly as the reference sets it. It sits below the
   header rather than over it (z-index under .hdr) so the bar slides up out
   of sight behind the nav, and the nav stays reachable while it is showing. */
.sticky{
  position:fixed;left:0;right:0;top:var(--hdr-h);z-index:50;
  display:grid;grid-template-columns:1fr auto auto;align-items:stretch;
  min-height:66px;background:var(--paper);
  border-bottom:1px solid var(--line);box-shadow:0 2px 14px rgba(0,0,0,.07);
  translate:0 -102%;transition:translate .26s var(--ease);
  visibility:hidden;
}
.sticky.is-show{translate:0 0;visibility:visible}
/* When the header has slid away the bar takes its place at the very top,
   moving on the same curve so the two read as one piece of chrome. */
body.is-hdr-off .sticky{top:0;transition:translate .26s var(--ease),top .3s var(--ease)}
.sticky__l{
  display:flex;flex-direction:column;justify-content:center;gap:3px;
  padding:10px 0 10px var(--gut);min-width:0;
}
.sticky__n{font-size:13px;font-weight:400;letter-spacing:.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sticky__p{font-size:12px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.sticky__meta{
  display:flex;align-items:center;gap:10px;padding:0 26px;
  font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-soft);
  white-space:nowrap;
}
/* The same crop of cloth as the chip in the buy panel, at bar scale. The
   URL is written here rather than inline because, unlike the buy-panel
   chip, this mark is not part of a radio group — there is one bar and one
   colourway, so there is nothing for a per-swatch custom property to vary. */
.sticky__sw{
  width:20px;height:20px;border-radius:50%;
  background:#cf2734 url('img/swatch-scarlet-red.png') 50% 50% / cover no-repeat;
  box-shadow:0 0 0 1px rgba(0,0,0,.16) inset;
}
.sticky__sep{width:1px;height:18px;background:var(--line-2)}
.sticky__btn{
  align-self:stretch;padding:0 clamp(30px,4vw,68px);
  background:var(--brand);color:#fff;
  font-size:12px;letter-spacing:.18em;text-transform:uppercase;
  transition:background .16s var(--ease);
}
.sticky__btn:hover{background:var(--brand-dk)}

/* ═══════════════ LIGHTBOX ═══════════════ */
.lb{
  position:fixed;inset:0;z-index:120;background:var(--paper);
  display:grid;grid-template-columns:112px minmax(0,1fr);
  opacity:0;transition:opacity .18s var(--ease);
}
/* This line is not tidiness — without it the whole page is dead to the mouse.
   The markup carries the `hidden` attribute, but `hidden` is only a browser
   default of display:none, and ANY author display wins over a browser default
   no matter how weak the selector looks. So `display:grid` above was keeping
   this sheet in the layout permanently: a fixed, full-window, z-index 120 pane
   at opacity 0 sitting over everything. Invisible, but it still catches every
   click and every hover — which is why the zoom mark never appeared on the
   photographs and why nothing opened when they were clicked.
   The dialog and the bag drawer further down each already carry their own
   guard for exactly this reason; the lightbox was the one that missed it. */
.lb[hidden]{display:none}
.lb.is-show{opacity:1}
.lb__x{
  position:absolute;top:18px;right:22px;z-index:3;
  width:44px;height:44px;display:grid;place-items:center;
  background:rgba(255,255,255,.9);border-radius:50%;
}
.lb__x svg{width:19px;height:19px}
.lb__x:hover{color:var(--brand)}

.lb__rail{
  display:flex;flex-direction:column;gap:8px;
  padding:18px 10px;overflow-y:auto;border-right:1px solid var(--line);
  scrollbar-width:thin;
}
.lb__th{padding:0;background:var(--panel);opacity:.62;transition:opacity .16s var(--ease)}
.lb__th img{width:100%;aspect-ratio:var(--shot);object-fit:cover;object-position:50% 22%}
.lb__th:hover{opacity:.9}
.lb__th.is-on{opacity:1;box-shadow:0 0 0 1px var(--ink)}

.lb__stage{display:grid;place-items:center;overflow:auto;padding:18px;background:var(--panel)}
.lb__stage img{max-width:100%;max-height:calc(100vh - 36px);width:auto;object-fit:contain}

.lb__nav{
  position:absolute;top:50%;translate:0 -50%;z-index:3;
  width:46px;height:46px;display:none;place-items:center;
  background:rgba(255,255,255,.9);border-radius:50%;
}
.lb__nav svg{width:19px;height:19px}
.lb__nav--prev{left:16px}
.lb__nav--next{right:16px}
.lb__count{display:none}

/* ── toast ─────────────────────────────────────────────────────── */
.toast{
  position:fixed;left:50%;bottom:30px;translate:-50% 12px;z-index:150;
  padding:13px 22px;background:var(--ink);color:#fff;
  font-size:12px;letter-spacing:.07em;
  opacity:0;pointer-events:none;transition:opacity .2s var(--ease),translate .2s var(--ease);
}
.toast.is-show{opacity:1;translate:-50% 0}

body.is-lock{overflow:hidden}

/* ═══════════════ DETAIL DIALOG ═══════════════
   The four buy-panel rows no longer expand in place — they open a panel over
   the page, exactly as the reference does: heavy title top-left, close mark
   top-right, and the list running in two columns underneath.

   The body is filled by CLONING the matching .acc__p node, class and all, so
   every rule from line 354 down keeps applying inside here for free. The only
   thing this block adds is the two-column split and a slightly larger reading
   size, because the panel is far wider than the buy column ever was. */
.dlg{position:fixed;inset:0;z-index:130;display:grid;place-items:center}
.dlg[hidden]{display:none}
.dlg__scrim{
  position:absolute;inset:0;background:rgba(20,18,15,.42);
  opacity:0;transition:opacity .24s var(--ease);
}
.dlg.is-show .dlg__scrim{opacity:1}
.dlg__win{
  position:relative;z-index:1;
  width:min(920px,calc(100vw - 2 * var(--gut)));max-height:min(760px,calc(100vh - 64px));
  display:flex;flex-direction:column;
  background:var(--paper);box-shadow:0 24px 60px rgba(0,0,0,.18);
  opacity:0;translate:0 14px;transition:opacity .26s var(--ease),translate .26s var(--ease);
}
.dlg.is-show .dlg__win{opacity:1;translate:0 0}
.dlg__hd{
  display:flex;align-items:flex-start;justify-content:space-between;gap:20px;
  padding:clamp(26px,3.2vw,40px) clamp(24px,3.2vw,44px) clamp(16px,1.8vw,22px);
}
.dlg__h{
  font-size:clamp(21px,2.1vw,30px);font-weight:400;letter-spacing:.005em;line-height:1.2;
  text-wrap:balance;
}
.dlg__x{
  flex:0 0 auto;width:40px;height:40px;display:grid;place-items:center;
  margin:-8px -8px 0 0;color:var(--ink);
  transition:rotate .25s var(--ease),color .15s var(--ease);
}
.dlg__x svg{width:20px;height:20px}
.dlg__x:hover{rotate:90deg;color:var(--brand)}
.dlg__b{
  padding:0 clamp(24px,3.2vw,44px) clamp(28px,3.4vw,44px);
  overflow-y:auto;overscroll-behavior:contain;
}
.dlg__b .acc__p{padding:0}
.dlg__b .acc__p p{font-size:14px;max-width:70ch}
.dlg__b .acc__p ul{
  grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:clamp(26px,4vw,64px);row-gap:11px;
  padding-top:4px;
}
.dlg__b .acc__p li{font-size:13.5px}
.dlg__b .acc__meta{font-size:11.5px}

/* ═══════════════ ADDED-TO-BAG DRAWER ═══════════════
   Desktop: a panel that slides in from the right edge, full height.
   Phone (below): the same content as a sheet rising from the bottom.
   One markup, two entrances — only the transform and the corner change. */
.bag{position:fixed;inset:0;z-index:140}
.bag[hidden]{display:none}
.bag__scrim{
  position:absolute;inset:0;background:rgba(20,18,15,.34);
  opacity:0;transition:opacity .26s var(--ease);
}
.bag.is-show .bag__scrim{opacity:1}
.bag__win{
  position:absolute;top:0;right:0;z-index:1;
  width:min(420px,100vw);height:100%;
  display:flex;flex-direction:column;gap:clamp(18px,2.2vw,26px);
  padding:clamp(24px,2.6vw,34px);
  background:var(--paper);box-shadow:-14px 0 46px rgba(0,0,0,.14);
  translate:100% 0;transition:translate .32s var(--ease);
  overflow-y:auto;overscroll-behavior:contain;
}
.bag.is-show .bag__win{translate:0 0}
.bag__x{
  position:absolute;top:14px;right:14px;
  width:38px;height:38px;display:grid;place-items:center;color:var(--ink);
  transition:rotate .25s var(--ease),color .15s var(--ease);
}
.bag__x svg{width:19px;height:19px}
.bag__x:hover{rotate:90deg;color:var(--brand)}

.bag__ok{
  display:flex;align-items:center;gap:10px;padding-right:44px;
  font-size:13px;letter-spacing:.09em;text-transform:uppercase;
}
.bag__tick{flex:0 0 auto;display:grid;place-items:center;width:24px;height:24px;color:var(--ok)}
.bag__tick svg{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.4}
.bag__tick path{stroke-linecap:round;stroke-linejoin:round}

.bag__i{display:grid;grid-template-columns:104px minmax(0,1fr);gap:16px;align-items:start}
.bag__img{width:100%;aspect-ratio:var(--shot);object-fit:cover;background:var(--stone)}
.bag__d{min-width:0}
.bag__v{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-mute)}
.bag__n{margin-top:6px;font-size:14px;font-weight:400;line-height:1.4;letter-spacing:.01em}
.bag__m{margin-top:8px;font-size:12px;color:var(--ink-soft)}
.bag__pr{margin-top:10px;font-size:13.5px;font-variant-numeric:tabular-nums}

.bag__act{display:grid;gap:10px;margin-top:auto}
.bag__act .btn{width:100%}

/* ═══════════════════════════════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════════════════════════════ */

/* Laptop — the nav is the first thing that runs out of room. */
@media (max-width:1280px){
  .hdr__nav{gap:14px}
  .hdr__nav a{font-size:11px;letter-spacing:.09em}
  .sticky__meta{padding:0 16px}
}

/* Narrow desktop / large tablet — the two columns stop working long before
   the phone breakpoint, because the buy panel needs ~380px to hold the size
   row without wrapping to three lines. Single column from here down. */
@media (max-width:1080px){
  .pdp{grid-template-columns:1fr}
  .buy{padding-inline:clamp(20px,5vw,54px)}
  .ctl__i{grid-template-columns:clamp(150px,22vw,205px) minmax(0,1fr)}
  .hdr__burger{display:grid;place-items:center;padding:7px}
  .hdr__nav{display:none}
  .hdr__logo{justify-self:start}
  .lb{grid-template-columns:88px minmax(0,1fr)}

  /* Recently viewed loses its side-by-side shape: the heading lies down
     across the top with the pill pushed to the far end of the same line. */
  .rv{grid-template-columns:1fr;gap:clamp(18px,2.4vw,28px)}
  .rv__head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px 20px}
  .rv__h{grid-area:1 / 1;flex-direction:row;gap:.3em;font-size:clamp(26px,4.2vw,40px)}
  .rv__note{grid-area:2 / 1;margin-top:2px;max-width:56ch}
  .pill--rv{grid-area:1 / 2 / span 2 / auto;margin-top:0;justify-self:end}
}

/* Tablet */
@media (max-width:860px){
  /* Definite track widths, never minmax(0,…): a zero minimum lets the grid
     squeeze every card into the visible width instead of overflowing, which
     is precisely how five cards ended up sharing one phone screen. */
  .also__row{grid-auto-columns:42vw}
  .rv__row{grid-auto-columns:44vw}
  .band__in{padding-inline:clamp(20px,6vw,48px)}

  /* Two columns: the vertical rules stop making sense once the row wraps,
     so they give way to plain gaps. */
  .foot__cols{grid-template-columns:repeat(2,minmax(0,1fr));gap:28px 0}
  .foot__c + .foot__c{border-left:0}
  .foot__c:nth-child(even){padding-right:0}
  .foot__c:nth-child(odd){padding-left:0}
  .foot__c--sign{grid-column:span 2;padding-inline:0}
  .jour__row{grid-template-columns:1fr;gap:14px}

  /* Point 11: from here down the detail shots are picture left, words
     right — one row each, so the three read as a list of features rather
     than three columns squeezed to a third of a phone. */
  .love__grid{grid-template-columns:1fr;gap:clamp(14px,2.4vw,22px)}
  .love__i{
    display:grid;grid-template-columns:minmax(0,40%) minmax(0,1fr);
    gap:clamp(14px,3vw,24px);align-items:center;
    background:var(--paper);padding:clamp(10px,1.6vw,16px);
  }
  .love__b{margin-top:0;grid-template-columns:auto minmax(0,1fr)}
  .love__ico{width:34px;height:34px}
  .love__ico svg{width:17px;height:17px}
}

/* ── Phone ───────────────────────────────────────────────────────
   The gallery becomes one swipe track: a single photograph at a time,
   snapped, with the counter bottom-left and the expand mark bottom-right.
   Add to bag leaves the panel and lives at the bottom of the window. */
@media (max-width:700px){
  :root{--hdr-h:56px}

  .is-hide-sm{display:none}

  /* One line, not three: the sentence sheds its two qualifying phrases
     rather than wrapping, which is what the reference band does. */
  .anno{min-height:34px;padding:8px 32px}
  .anno p{font-size:10px;letter-spacing:.06em;white-space:nowrap}
  .anno__wide{display:none}
  .anno__x{right:8px}
  .anno__x svg{width:13px;height:13px}

  /* ── the header rides ON the photograph ──────────────────────
     The reference gives a phone no white band at all: the announcement bar
     ends, the picture begins, and the menu, search and bag sit straight on
     top of it. Two things make that work.

     First, a negative bottom margin exactly one header tall. The header is
     still in normal flow — so it still sticks, still hides on the way down,
     still drops back on the way up — but the gallery underneath it starts
     at the header's own top edge instead of below it.

     Second, no ground of its own until it needs one. Transparent over the
     picture; solid the moment the picture has scrolled past (JS sets
     is-hdr-solid) or the drawer is open, so the dark icons are never dark
     marks on dark page furniture. */
  .hdr{
    margin-bottom:calc(-1 * var(--hdr-h));
    background:transparent;border-bottom-color:transparent;
    transition:translate .3s var(--ease),background .2s var(--ease),border-color .2s var(--ease);
  }
  body.is-hdr-solid .hdr,
  .hdr:has(.mnav.is-open){background:var(--paper);border-bottom-color:var(--line)}

  /* Wordmark hard left, then search, bag and the menu mark grouped hard
     right — the reference keeps all three controls in one cluster. */
  .hdr__in{display:flex;align-items:center;gap:12px}
  .hdr__logo{order:1}
  .hdr__logo img{width:118px}
  /* The wordmark has a real alpha channel now, so it lies straight on the
     photograph. A whisper of light behind it keeps the bronze legible where
     the cloth happens to be the same mid-tone; it costs nothing once the
     header takes its white ground back, so it goes away then. */
  .hdr__logo img{filter:drop-shadow(0 0 3px rgba(255,255,255,.7))}
  body.is-hdr-solid .hdr__logo img{filter:none}
  .hdr__ico{order:2;margin-left:auto;gap:2px}
  .hdr__burger{order:3;padding:7px 0 7px 8px}

  /* Absolute, so opening it cannot grow the header past the negative margin
     and shove the photograph down the page. */
  .mnav{
    position:absolute;left:0;right:0;top:100%;
    background:var(--paper);border-bottom:1px solid var(--line);
  }

  .gal__track{
    display:flex;gap:0;overflow-x:auto;scroll-snap-type:x mandatory;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .gal__track::-webkit-scrollbar{display:none}
  .gal__f,.gal__f--full,.gal__f--half{flex:0 0 100%;scroll-snap-align:center;grid-column:auto}
  .gal__f img{object-position:50% 18%}
  .gal__zoom{display:none}
  .gal__ctl{display:none}

  /* Both are lozenges, not the hard-cornered tiles they were: the reference
     rounds every mark that sits on top of a photograph. */
  .gal__count{
    display:block;position:absolute;left:14px;bottom:16px;z-index:2;
    padding:7px 15px;border-radius:999px;background:rgba(255,255,255,.94);
    font-size:11px;letter-spacing:.1em;color:var(--ink);
    font-variant-numeric:tabular-nums;
  }
  .gal__expand{
    display:grid;place-items:center;position:absolute;right:14px;bottom:16px;z-index:2;
    width:40px;height:40px;border-radius:50%;
    background:rgba(255,255,255,.94);color:var(--ink);
  }
  .gal__expand svg{width:16px;height:16px}

  .buy{padding:22px 20px 26px}
  .crumb{margin-bottom:14px;font-size:10px}
  .buy__name{font-size:20px}
  .size{min-width:48px;min-height:44px;flex:1 1 auto}

  /* The inline Add to bag STAYS on the phone — the reference puts a dark
     full-width button right under the size grid, and the pinned bar only
     appears after that button has scrolled away. (It is also what re-arms
     the IntersectionObserver: with display:none the observed node never
     intersects and the bar could never decide to show itself.) */
  .atc .btn{min-height:52px;letter-spacing:.16em}

  /* Point 13: the two interleaved plates. Hidden on desktop — never even
     fetched — they appear here to give the phone the reference's rhythm:
     button, photograph, description, detail rows, photograph, the look.
     Full-bleed, so the negative inline margin cancels .buy's own padding. */
  .inl{display:block;margin:clamp(22px,5.6vw,32px) -20px 0}
  .inl img{width:100%;height:auto;display:block;background:var(--stone)}
  .inl + .desc{margin-top:clamp(18px,4.6vw,26px)}

  /* Heading and pager share a line and wrap onto two when the words are
     long — which is what the reference does at this width. */
  .ctl__top{flex-wrap:wrap;gap:8px 14px}
  .ctl__i{grid-template-columns:minmax(0,38%) minmax(0,1fr);gap:14px}
  .ctl__h{font-size:17px}
  .ctl__b h3{font-size:13px}

  /* Both carousels are scrolled by thumb here, so the arrows are dead
     weight — and the paddles would sit on top of the photographs. */
  .pill{display:none}
  .rv__pad{display:none}

  .also{padding-top:34px}
  .also__row{grid-auto-columns:60vw;scroll-padding-inline:var(--gut)}
  .also__top h2{font-size:16px}

  .rv{padding-block:clamp(34px,8vw,54px)}
  .rv__h{font-size:clamp(26px,8vw,34px)}
  .rv__note{font-size:12px}
  .rv__row{grid-auto-columns:60vw;scroll-padding-inline:var(--gut)}

  .love__in{padding-block:clamp(36px,9vw,56px)}
  .love__h{font-size:clamp(20px,5.6vw,26px)}
  .love__eyebrow{font-size:10.5px}
  .love__b h3{font-size:12.5px}
  .love__b p{font-size:12px}

  /* One article under the other, thumbnail smaller again. At this width a
     footer shelf should read as two lines of text with a picture beside
     each — not as cards. The rule above it is dropped: the last accordion
     already draws one, and two hairlines a pixel apart look like a mistake. */
  .jour{border-top:0}
  .jour .shell{padding-block:22px}
  /* No room for three tracks here. The band collapses to one column, the
     articles are pulled to the top of it, and the two topic stacks fall in
     underneath as centred rows — six short marks reading as one line of
     subjects rather than as two columns squeezed to nothing. */
  .jour__band{width:auto;grid-template-columns:1fr;gap:16px}
  .jour__row{order:-1;grid-template-columns:1fr;gap:16px;padding-inline:0}
  /* No room for three tracks, so the dividing rules go and the two stacks
     fall in under the articles as centred rows — six short marks reading as
     one line of subjects rather than as columns squeezed to nothing. */
  .jour__tags{display:flex;flex-wrap:wrap;justify-content:center;gap:9px 16px}
  .jour__band > .jour__tags:first-child{padding-right:0;border-right:0;text-align:center}
  .jour__band > .jour__tags:last-child{padding-left:0;border-left:0}
  .jart a{grid-template-columns:64px minmax(0,1fr);gap:14px}
  .jart__n{font-size:13px}

  /* ── the campaign band: the copy comes off the picture ────────
     The mobile crop is not the desktop crop scaled down, it is a different
     piece of artwork — and it carries the campaign words inside the image
     itself. Drawing our own eyebrow and headline over it sets words on top
     of words, which is the mess in the screenshot.

     So here the copy steps off the photograph altogether: the picture runs
     at its own crop with nothing over it, and the line and the two buttons
     sit underneath on the warm panel. The scrim goes with it — it exists to
     hold white text and there is no white text left. The eyebrow goes too:
     the artwork already says "Oxford Shirts", and "The Oxford Edit"
     immediately below it is the same thought twice. */
  .band{background:var(--panel)}
  .band::after{display:none}
  .band img{height:auto}
  .band__in{
    position:static;max-width:none;
    gap:14px;padding:22px 20px 26px;color:var(--ink);
  }
  .band__eyebrow{display:none}
  .band__h{font-size:23px;max-width:22ch}
  /* The ghost buttons were white-on-photograph; on the panel they need ink. */
  .band__cta{width:100%;margin-top:2px}
  .band__cta .btn{flex:1 1 0;min-height:46px;font-size:11px;padding:0 14px}
  .band__cta .btn--ghost-light{border-color:var(--line-2);color:var(--ink)}
  .band__cta .btn--ghost-light:hover{background:var(--ink);color:#fff}

  /* ── the phone footer ─────────────────────────────────────────
     Sign-up first, then the three accordions, then the journal, the social
     tiles and the legal line — the reference order. The column is moved with
     order rather than in the markup, because on a wide screen it has to stay
     the fourth column, on the right, exactly where it is written.

     Accordions are a button with aria-expanded plus a panel, rather than
     <details>, because forcing <details> back open at a wider viewport is
     not reliable across browsers. */
  .foot__cols{grid-template-columns:1fr;gap:0;padding-block:0 4px}
  .foot__c{border-bottom:1px solid var(--line);padding-inline:0}
  .foot__c + .foot__c{border-left:0}
  .foot__c--sign{order:-1;grid-column:auto;padding:26px 0 28px}
  .foot__consent{max-width:none;font-size:10.5px;line-height:1.8}

  /* A plus that turns into a cross. The columns start open, the way the
     reference ships them: in a footer the mark is an offer to fold a list
     away, not an invitation to discover one. */
  .foot__t{padding:17px 0;cursor:pointer}
  .foot__t svg{display:block;color:var(--brand);transition:rotate .22s var(--ease)}
  .foot__t[aria-expanded="true"] svg{rotate:45deg}
  .foot__p{display:none;padding-bottom:20px}
  .foot__c.is-open .foot__p{display:grid;gap:14px}
  .foot__f .btn{padding:0 22px;letter-spacing:.1em}

  .foot__guides{gap:12px}

  /* The Add-to-bag bar is fixed to the bottom of the window, so the last
     40-odd pixels of the page are permanently underneath it — which is what
     was swallowing the payment row and the copyright line. The page has to
     end above the bar, so the bottom of the footer reserves the bar's height
     plus the home-indicator strip it sits on.

     Reserved always, not only while the bar is showing: the bar is hidden
     only while the real Add-to-bag button is on screen, which is near the top
     of the page, so this strip is never visible when it is not needed — and
     adding the space on the fly would jog the page under the reader's thumb. */
  .foot__base .shell{padding-bottom:calc(58px + 18px + env(safe-area-inset-bottom))}

  /* ── Add to bag, edge to edge ─────────────────────────────────
     The reference pins a bar with no margin at all — the button IS the bar.
     So no padding, no border, no gap on any side. The one exception is the
     safe-area inset, and that is not spacing: it is the strip of screen the
     home indicator sits on. The bar takes the button's own colour so that
     strip reads as part of the button rather than as a white sliver under
     it. */
  .sticky{
    top:auto;bottom:0;grid-template-columns:1fr;
    min-height:0;border:0;background:var(--brand);
    padding:0 0 env(safe-area-inset-bottom);
    translate:0 102%;box-shadow:0 -2px 14px rgba(0,0,0,.09);
  }
  /* The bar lives at the bottom here, so it must not keep the desktop rule
     that hands it top:0 when the header retires — a fixed box with both top
     and bottom set stretches over the entire window. */
  body.is-hdr-off .sticky{top:auto}
  .sticky__l,.sticky__meta{display:none}
  .sticky__btn{
    width:100%;min-height:58px;padding:0 20px;
    display:grid;place-items:center;letter-spacing:.16em;
  }

  /* Lightbox loses the rail: one photograph, a counter, two paddles, an X.
     Nothing else on the screen. */
  .lb{grid-template-columns:1fr;background:#fff}
  .lb__rail{display:none}
  .lb__stage{padding:0;background:#fff}
  .lb__stage img{max-height:100vh;width:100%;height:100vh;object-fit:contain}
  .lb__x{top:12px;right:12px;width:40px;height:40px;background:rgba(255,255,255,.86)}
  .lb__nav{display:grid;width:42px;height:42px;top:auto;bottom:22px;translate:0 0}
  .lb__nav--prev{left:calc(50% - 92px)}
  .lb__nav--next{left:calc(50% + 50px);right:auto}
  .lb__count{
    display:block;position:absolute;left:50%;bottom:32px;translate:-50% 0;z-index:3;
    font-size:12px;letter-spacing:.1em;color:var(--ink);font-variant-numeric:tabular-nums;
  }

  /* Both overlays become sheets that rise from the bottom edge. The dialog
     takes nearly the whole screen because its lists are long; the bag takes
     only the height its content needs. */
  .dlg{place-items:end center}
  .dlg__win{
    width:100vw;max-height:92vh;
    translate:0 100%;transition:translate .3s var(--ease),opacity .2s var(--ease);
  }
  .dlg.is-show .dlg__win{translate:0 0}
  .dlg__hd{padding:24px 20px 14px}
  .dlg__h{font-size:20px}
  .dlg__b{padding:0 20px calc(28px + env(safe-area-inset-bottom))}
  .dlg__b .acc__p ul{grid-template-columns:1fr;row-gap:10px}

  .bag__win{
    top:auto;bottom:0;right:0;left:0;
    width:100%;height:auto;max-height:88vh;
    padding:24px 20px calc(24px + env(safe-area-inset-bottom));
    gap:20px;box-shadow:0 -14px 46px rgba(0,0,0,.16);
    translate:0 100%;
  }
  .bag__i{grid-template-columns:88px minmax(0,1fr)}
  .bag__act{margin-top:4px}

  .toast{bottom:88px}
}

@media (max-width:420px){
  .buy__name{font-size:18.5px}
  .sizes{gap:6px}
  .size{min-width:44px;font-size:11px}
  .foot__guides a{font-size:10.5px}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;
  }
}
