/* Preston Pollard — /shop
   Direction A, "The Drop". A deliberately separate system from the speaking
   site: one condensed face, square corners, white ground, no accent colour in
   the interface. The garments are the only colour on the page, which is how
   Fear of God's own collection pages work. Documented in DESIGN.md. */

:root {
  /* ground */
  --paper: #ffffff;
  --well: #f0efed;          /* product wells */
  --hair: #e6e6e3;          /* every rule on the page */

  /* ink */
  --ink: #111111;
  --ink-2: #555555;
  --mute: #9a9a95;          /* collection lines, meta */
  --on-dark: #ffffff;

  /* type — one face, no pairing */
  --font: "Archivo Narrow", "Arial Narrow", system-ui, sans-serif;
  --t-cta: 14px;
  --t-band: clamp(20px, 2.6vw, 30px);
  --t-nav: 11px;
  --t-name: 12px;
  --t-price: 11.5px;
  --t-meta: 9.5px;

  /* space & motion */
  --gut: clamp(16px, 3.4vw, 44px);
  --bar-h: 73px;    /* fixed .bar; content that tops out under it must clear this */
  --max-w: 1500px;   /* caps cell width so photos are not shown past their detail */
  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  --dur: 600ms;
}

* { box-sizing: border-box; }
html, body { overflow-x: clip; }
html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  scroll-behavior: smooth;
}
/* The shop opens on an ink hero that runs under Safari's own chrome, so the
   canvas behind the safe areas is ink as well. Without this the strip behind the
   status bar and the one behind the home indicator show the page's white, which
   is the white above and below the photograph. The body stays paper, so nothing
   below the hero changes. */
html.shop { background: var(--ink); }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
}
img { max-width: 100%; display: block; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 10;
  background: var(--ink); color: var(--on-dark);
  padding: 14px 18px; font-size: 12px; min-height: 44px;
  text-transform: uppercase; letter-spacing: 0.16em; text-decoration: none;
}
.skip:focus { left: 0; }

.bar:not(.solid) :where(a):focus-visible { outline-color: var(--on-dark); }
:where(a, button):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* ---------------- nav ---------------- */
.bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  padding: 14px var(--gut);
  position: fixed; top: 0; left: 0; right: 0; z-index: 5;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
/* scrim so the links stay legible over a pale sky */
.hero::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 160px;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(0,0,0,0.52), rgba(0,0,0,0));
}
.bar.solid { background: var(--paper); border-bottom-color: var(--hair); }

.bar a, .bar span {
  font-size: var(--t-nav);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--on-dark);
  text-decoration: none;
  white-space: nowrap;
}
.bar nav { display: flex; gap: clamp(12px, 1.8vw, 22px); }
.bar .right { display: flex; gap: clamp(12px, 1.8vw, 22px); justify-content: flex-end; }
.bar a, .wordmark { min-height: 44px; display: inline-flex; align-items: center; }
.bar a[aria-current="page"] { text-decoration: underline; text-underline-offset: 4px; }
.bar a:hover { opacity: 0.72; }
.bar.solid a, .bar.solid .wordmark { color: var(--ink); }
.bar.solid a:hover { opacity: 1; color: var(--ink-2); }
.wordmark {
  font-size: 13px; font-weight: 600;
  letter-spacing: 0.3em; text-align: center;
  text-transform: uppercase; text-decoration: none; color: var(--on-dark);
}
@media (max-width: 720px) {
  .bar { grid-template-columns: 1fr auto; }
  .bar nav { display: none; }
  .wordmark { text-align: right; }
}

/* ---------------- hero ---------------- */
.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* The hero owns the whole first screen, the way the reference does: nothing
   of the page below it shows until you scroll. Before this it ran to the
   image's own height and left the collection strip visible underneath. */
/* 100svh is the viewport with Safari's toolbars showing; the moment they retract
   the hero is short and the colour panel below it shows above the fold. dvh
   tracks the real height, so the first screen is always only the hero. */
/* +2px because a viewport height is not always a whole number: at 100dvh exactly,
   a fractional screen leaves a hairline of the panel below showing under the
   photograph, which reads as the top border of the next shot. */
.hero {
  position: relative; background: var(--well);
  height: 100svh;
  /* +2px because a viewport height is not always a whole number: at exactly
     100dvh a fractional screen leaves a hairline of the next photograph under
     this one. */
  height: calc(100dvh + 2px);
  /* dvh lags the real viewport while Safari's toolbar is collapsing, which is
     the other way the next photograph gets on screen. While the toolbar is up
     this pushes the panel down by exactly the toolbar's height, so the lag
     reveals paper rather than her; once it retracts lvh equals dvh and the
     margin is zero, so nothing is added to the scroll. */
  margin-bottom: calc(100lvh - 100dvh);
}
.hero img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  /* favours the top, so the crop trims legs rather than heads */
  object-position: 50% 20%;
}
/* On a phone the shot cannot fill the screen and keep the three of them: it is a
   0.80 frame on a screen of about 0.46, both outer models run to its edges, and
   her face begins 10px from the left. So the whole frame sits at the top of the
   screen at full width, and the rest of the screen is the same photograph,
   blurred and darkened, instead of a white gap. The hero is 100lvh here — the
   tallest the viewport ever gets — so no state of Safari's toolbar can bring the
   next photograph into view, and the Shop button is lifted off the toolbar by
   the difference. */
.hero__cta {
  position: absolute; left: 50%; bottom: clamp(28px, 4vw, 40px); transform: translateX(-50%);
  background: var(--ink); color: var(--on-dark);
  width: min(70vw, 310px);
  min-height: clamp(47px, 5.5vw, 56px);
  font-size: var(--t-cta); text-transform: uppercase; letter-spacing: 0.05em;
  text-decoration: none; white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: center;
  transition: opacity var(--dur) var(--ease);
}
.hero__cta:hover { opacity: 0.86; }

@media (max-aspect-ratio: 1/1) {
  /* Fear of God's own phone hero, which Preston pointed at: the photograph covers
     the whole screen and the models are cut by the frame. So this one fills too,
     centred on the middle model and the print on his back, with nothing over it
     but the Shop button. 100lvh is the tallest the viewport ever gets, so no state
     of Safari's toolbar brings the panel below into view, and the button is held
     clear of the toolbar by the difference between lvh and svh. */
  .hero { height: 100svh; height: 100lvh; margin-bottom: 0; background: var(--ink); }
  .hero img { width: 100%; height: 100%; }
  /* the phone frame is cut to a phone's shape, so cover fills it without
     throwing any width away and all three stay in */
  .hero img { object-fit: cover; object-position: 50% 50%; }
  /* a little more scrim than the desktop's, so the wordmark holds over the sky */
  .hero::after { height: 210px; background: linear-gradient(to bottom, rgba(17,17,17,0.6), rgba(17,17,17,0)); }
  .hero__cta { bottom: clamp(28px, 4vw, 40px); bottom: calc(100lvh - 100svh + clamp(28px, 4vw, 40px)); }
}

/* ---------------- removed: type lockup ---------------- */



/* Keep the product area inside a container. The source photos carry about
   220px of real detail, so a full-bleed 3-up grid on a wide monitor was
   printing them at 2-3x that and they read blurry. Four narrower columns
   inside a capped container keeps each cell near 360px. */
.contain { max-width: var(--max-w); margin-inline: auto; }

/* ---------------- collection strip ---------------- */
.strip {
  scroll-margin-top: 58px;
  display: flex; justify-content: space-between; gap: 16px;
  padding: 12px var(--gut);
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.16em;
  color: var(--ink-2);
}

/* ---------------- grid — P1 stacked caption ---------------- */
.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(20px, 2.2vw, 32px);
  padding: clamp(20px, 2.2vw, 32px) var(--gut) clamp(34px, 4vw, 56px);
}
@media (max-width: 760px) { .grid { gap: 14px; padding-inline: 14px; } }

.cell { background: var(--paper); }
.cell > a { display: block; text-decoration: none; color: inherit; }
/* the frames are levelled onto this same tone by build-product-frames.py, so
   the garment reads as floating on the cell rather than on a paler rectangle */
.cell .well { display: block; background: var(--well); aspect-ratio: 3 / 4; overflow: hidden; }
.cell .well img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform var(--dur) var(--ease);
}
.cell > a:hover .well img,
.cell > a:focus-visible .well img { transform: scale(1.025); }

.cell .cap { display: block; padding: 12px clamp(14px, 1.4vw, 20px) 0; }
.cell .k {
  display: block; margin-bottom: 5px;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--mute);
}
.cell .n { display: block; margin-bottom: 3px; font-size: var(--t-name); color: var(--ink); }
.cell .p { font-size: var(--t-price); color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* no 1-up breakpoint on purpose: 2-up halves the scroll and keeps each cell
   near the source photos' real detail instead of upscaling past it */
@media (max-width: 520px) {
  .cell .cap { padding-inline: 12px; }
  .cell .k { display: none; }   /* the collection strip above already names it */
}


/* ---------------- spec ---------------- */
.spec {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(20px, 2.2vw, 32px);
  margin: 0;
  padding: clamp(26px, 3vw, 38px) var(--gut);
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
}
.spec > div { padding: 0; }
.spec dt {
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--ink-2); margin-bottom: 7px;
}
.spec dd { margin: 0; font-size: 12px; line-height: 1.45; color: var(--ink); }
@media (max-width: 760px) { .spec { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px clamp(20px, 2.2vw, 32px); } }



/* The second campaign panel and the collectible panel were both full-screen
   photographs under the hero. Preston asked for both off on 2026-10-17 — the
   hero is the only photograph on /shop now — so their styles went with them.
   The board lives under the clothes on /collection instead, as .more. */

/* The collection page opens straight onto its first row with no hero beneath
   the fixed bar, so it has to pay for that height itself. */
body.collection main { padding-top: var(--bar-h); }

/* The collection page opens straight onto its first row with no hero beneath
   the fixed bar, so it has to pay for that height itself. */
body.collection main { padding-top: var(--bar-h); }

/* ---------------- the one extra thing, under the clothes ---------------- */
/* Small on purpose: the garments are the page, and the board reads as a
   footnote to them until it is opened. */
.more { padding: clamp(18px, 2.2vw, 28px) var(--gut) clamp(34px, 4vw, 56px); }
.more a {
  display: inline-flex; align-items: center; gap: clamp(16px, 2vw, 28px);
  text-decoration: none; color: inherit;
}
.more .well {
  flex: 0 0 auto; display: block; overflow: hidden;
  width: clamp(104px, 26vw, 170px); aspect-ratio: 3 / 4;
  background: var(--well);
}
.more .well img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur) var(--ease); }
.more a:hover .well img, .more a:focus-visible .well img { transform: scale(1.025); }
.more .cap { display: block; }
.more .k {
  display: block; margin-bottom: 5px;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--mute);
}
.more .n { display: block; margin-bottom: 3px; font-size: var(--t-name); color: var(--ink); }
.more .p { font-size: var(--t-price); color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* ---------------- the line — closing panel ---------------- */
/* The one place this page raises its voice. Ink ground against a page that is
   otherwise all white, so it reads as a break rather than another row. No
   photograph on purpose: all four product shots are already in the grid above,
   and on a four-item page reusing one of them reads as a repeat. */
.line {
  background: var(--ink); color: var(--on-dark);
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: space-between;
  gap: clamp(28px, 4vw, 56px);
  padding: calc(var(--bar-h) + clamp(18px, 2vw, 30px)) var(--gut) clamp(26px, 3.2vw, 48px);
}
.line__meta {
  margin: 0;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: rgba(255, 255, 255, 0.6);
}
.line__h {
  margin: 0;
  font-size: clamp(50px, 13.2vw, 196px);
  line-height: 0.86; font-weight: 700;
  text-transform: uppercase; letter-spacing: -0.025em;
}
.line__foot {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) auto;
  gap: clamp(18px, 2.4vw, 32px);
  align-items: end;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  padding-top: 18px;
}
.line__say {
  margin: 0; max-width: 46ch;
  font-size: 14px; line-height: 1.5; color: rgba(255, 255, 255, 0.88);
}
.line__k {
  margin: 0;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; line-height: 1.9; color: rgba(255, 255, 255, 0.6);
}
.line__cta {
  justify-self: end;
  display: inline-flex; align-items: center; justify-content: center;
  width: min(70vw, 260px); min-height: 50px;
  background: var(--paper); color: var(--ink);
  font-size: var(--t-cta); text-transform: uppercase; letter-spacing: 0.05em;
  text-decoration: none; white-space: nowrap;
  transition: opacity var(--dur) var(--ease);
}
.line__cta:hover { opacity: 0.86; }
.line :where(a):focus-visible { outline-color: var(--on-dark); }

@media (max-width: 860px) {
  .line__foot { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .line__cta { justify-self: stretch; width: 100%; }
}

/* ---------------- footer ---------------- */
.foot {
  display: flex; flex-wrap: wrap; gap: 14px clamp(18px, 4vw, 48px);
  justify-content: space-between;
  padding: clamp(26px, 4vw, 40px) var(--gut);
  border-top: 1px solid var(--hair);
}
.foot nav { display: flex; flex-wrap: wrap; gap: 14px clamp(18px, 3vw, 34px); }
.foot a {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.16em;
  color: var(--ink); text-decoration: none;
  min-height: 44px; display: inline-flex; align-items: center;
}
.foot a:hover { text-decoration: underline; text-underline-offset: 4px; }
.foot p { margin: 0; align-self: center; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.16em; color: var(--mute); }

/* ---------------- scroll reveal ---------------- */
.reveal { opacity: 0; transform: translateY(14px); }
.reveal.in {
  opacity: 1; transform: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.no-js .reveal, .reveal.static { opacity: 1; transform: none; }


/* ---------------- page open ---------------- */
/* Same entrance as the speaking site, on this page's own curve: the
   campaign image settles out of a slow push-in while the page fades
   up, and the Shop control rises a beat behind it. */
@keyframes page-in   { from { opacity: 0; } }
@keyframes hero-sink { from { transform: scale(1.06); } }
/* .hero__cta is centred with translateX(-50%), so its own keyframe has
   to carry that through or the button snaps to the left edge for the
   length of the animation. */
@keyframes cta-rise  { from { opacity: 0; transform: translateX(-50%) translateY(14px); } }

/* Opacity only on <body>. A transform here would make body the
   containing block for position: fixed and strand .bar mid-page;
   opacity makes a stacking context but no containing block. */
body { animation: page-in 500ms var(--ease) both; }

.hero img    { animation: hero-sink 1600ms var(--ease) both; }
.hero__cta   { animation: cta-rise 700ms var(--ease) 300ms both; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;   /* else fill-mode: both holds the hidden state for the delay */
  }
  .reveal { opacity: 1; transform: none; }
}

/* ---------------- product page ---------------- */
/* Direction B, picked by Adrian 2026-10-16: the garment owns the first screen,
   you swipe through front, back and the sleeve label, and the buy control is
   held at the bottom of the screen the whole time. The panel is light rather
   than ink because every frame is a studio flat on the well's own paper — on
   ink the paper would read as a lit rectangle around the garment. So the
   garment panel is light and the chrome around it is ink, which is the same
   split the reference's own product pages use. */
body.product main { padding-top: var(--bar-h); }
.pdp { max-width: var(--max-w); margin-inline: auto; }

.pdp__gallery {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  background: var(--well);
}
.pdp__gallery::-webkit-scrollbar { display: none; }
.pdp__slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  background: var(--well);
}
.pdp__slide img {
  width: 100%;
  /* The bar (73), the dots (84) and the buy control (82) each hold their own
     height on the first screen and the garment takes the rest, cropping the
     frame's own paper rather than sitting small inside it — the point of this
     layout is that the garment owns the screen.
     150vw is the floor under that crop: the frames carry 10% of paper either
     side of the garment, and past 1.67x the width the crop would eat into it.
     On a tall phone the cap leaves about 20px of the name showing below the
     dots, which is an invitation to scroll rather than a gap. */
  height: min(calc(100svh - var(--bar-h) - 166px), 150vw);
  object-fit: cover;
}

.pdp__dots {
  display: flex; justify-content: center; gap: 10px;
  padding: 18px 0 22px;
  background: var(--well);
}
.pdp__dots button {
  width: 44px; height: 44px; padding: 0;
  border: 0; background: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.pdp__dots button::before {
  content: ""; width: 7px; height: 7px;
  background: var(--mute);
  transition: background var(--dur) var(--ease);
}
.pdp__dots button[aria-current="true"]::before { background: var(--ink); }

.pdp__info { padding: clamp(24px, 3vw, 36px) var(--gut) 0; }
.pdp__name {
  margin: 0;
  font-size: clamp(26px, 5.4vw, 38px); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; line-height: 1.05;
}
.pdp__meta {
  margin: 8px 0 0;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--mute);
}
.pdp__price { margin: 14px 0 0; font-size: 16px; color: var(--ink); font-variant-numeric: tabular-nums; }

.pdp__block { margin-top: clamp(22px, 2.6vw, 32px); border-top: 1px solid var(--hair); padding-top: 18px; }
.pdp__block > p { margin: 0 0 10px; font-size: 13px; line-height: 1.6; color: var(--ink-2); max-width: 54ch; }
.pdp__block > p:last-child { margin-bottom: 0; }
.pdp__k {
  margin: 0 0 12px;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--mute);
}
.pdp__spec { margin: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px clamp(20px, 2.2vw, 32px); }
.pdp__spec > div { padding: 0; }
.pdp__spec dt {
  margin: 0 0 6px;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--mute);
}
.pdp__spec dd { margin: 0; font-size: 12px; line-height: 1.45; color: var(--ink); }
.pdp__spec dd a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.pdp__spec dd a:hover { color: var(--ink-2); }

.pdp__links { display: flex; flex-direction: column; align-items: flex-start; margin-top: clamp(22px, 2.6vw, 32px); }
.pdp__back {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: var(--ink-2); text-decoration: none;
}
.pdp__back:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 4px; }

/* The buy control is pinned to the bottom of the screen on a phone, so it is
   reachable from any point in the page, and the page pays for its height at
   the end so the footer is never under it. */
.pdp__buy {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 4;
  background: var(--ink);
  padding-bottom: env(safe-area-inset-bottom);
}
.pdp__buy a,
.pdp__buy button {
  display: flex; align-items: center; justify-content: center;
  min-height: 58px; padding: 0 var(--gut);
  color: var(--on-dark); text-decoration: none;
  font-size: var(--t-cta); text-transform: uppercase; letter-spacing: 0.16em;
  font-family: inherit;
  width: 100%; border: 0; background: none;
  transition: opacity var(--dur) var(--ease);
}
.pdp__buy a:hover { opacity: 0.82; }
.pdp__buy button[disabled] { opacity: 0.55; cursor: not-allowed; }
.pdp__buy :where(a):focus-visible { outline-color: var(--on-dark); outline-offset: -4px; }
.pdp__buy p {
  margin: 0; padding: 0 var(--gut) 10px; text-align: center;
  font-size: var(--t-meta); text-transform: uppercase;
  letter-spacing: 0.2em; color: rgba(255,255,255,0.55);
}
body.product .foot { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }

/* Desktop: the three frames stack and the buy column holds beside them. The
   carousel and its dots are a phone affordance and go away here. */
@media (min-width: 900px) {
  .pdp {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: clamp(20px, 2.2vw, 32px);
    padding: clamp(20px, 2.2vw, 32px) var(--gut) clamp(34px, 4vw, 56px);
  }
  .pdp__gallery {
    display: grid; gap: clamp(20px, 2.2vw, 32px);
    overflow: visible; background: none;
  }
  .pdp__slide img { height: auto; aspect-ratio: 3 / 4; object-fit: cover; }
  .pdp__dots { display: none; }
  .pdp__info { padding: 0; position: sticky; top: calc(var(--bar-h) + 24px); align-self: start; }
  .pdp__buy {
    position: static; background: none; padding: 0;
    margin-top: clamp(22px, 2.6vw, 32px);
  }
  .pdp__buy a,
.pdp__buy button { background: var(--ink); }
  .pdp__buy p { color: var(--mute); padding: 10px 0 0; text-align: left; }
  body.product .foot { padding-bottom: clamp(26px, 4vw, 40px); }
}
