/*
 * Gallery, catalog and footer.
 *
 * Normal document flow throughout. Interaction polish is limited to
 * hover and focus states plus one subtle entrance; there is no scroll
 * choreography anywhere on this page.
 */

/* ── shared section furniture ───────────────────────────── */

.sec-head {
  max-width: var(--measure);
  margin: 0 auto clamp(28px, 5vh, 52px);
}

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

.sec-head h2 {
  margin: 0 0 8px;
  font-size: clamp(28px, 3vw + 12px, 44px);
  line-height: 1.08;
  letter-spacing: -.02em;
}

.lede {
  margin: 0;
  max-width: 56ch;
  color: var(--ink-soft);
}

.button {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 8px;
  padding: 13px 26px;
  border-radius: 999px;
  background: var(--accent-text);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 10px 22px -12px rgba(162, 46, 63, .8);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.button::after { content: "→"; }

.button:hover,
.button:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 16px 28px -12px rgba(162, 46, 63, .85);
}

/*
 * The second shopping destination. Same size and target as the first so
 * neither is hard to hit, but outlined rather than filled — Mainstore
 * first, Marketplace beside it, not two identical calls to action.
 */
.button--quiet {
  background: rgba(255, 255, 255, .78);
  color: var(--accent-text);
  box-shadow: inset 0 0 0 1px rgba(162, 46, 63, .32);
}

.button--quiet:hover,
.button--quiet:focus-visible {
  background: var(--white);
  box-shadow: inset 0 0 0 1px rgba(162, 46, 63, .5),
              0 12px 24px -14px rgba(162, 46, 63, .55);
}


/* ── the tone wash ──────────────────────────────────────── */

/*
 * Every tonal change on the page, in one element.
 *
 * Sections deliberately have no background of their own. Any section
 * background — however soft its own gradient — still begins at a section
 * boundary, and that is exactly the edge being removed: the hero's floor
 * ended in a hard rectangle and the gallery's wash started at a different
 * tone, so the page read as two stacked backgrounds.
 *
 * This sits above the shader and the heart sheet and below all content.
 * It is positioned 18vh above <main>, i.e. inside the hero, and is only
 * ~40% of the way up its own ramp as it crosses the boundary — so there
 * is no scroll position at which the change is a line rather than a
 * gradient. It ends by fading back to nothing over the last 24vh so the
 * hearts return under the footer with no edge there either.
 */
main { position: relative; }

.wash {
  position: absolute;
  left: 0;
  right: 0;
  top: -18vh;
  bottom: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    /* still hero: a warm deepening, standing in for the old floor */
    rgba(238, 194, 205, 0)    0,
    rgba(238, 194, 205, .10)  7vh,
    rgba(243, 214, 222, .26)  14vh,
    /* the hero/gallery boundary falls here, mid-ramp */
    rgba(248, 230, 234, .42)  18vh,
    rgba(252, 240, 242, .66)  34vh,
    rgba(253, 242, 244, .82)  76vh,
    rgba(253, 242, 244, .86)  150vh,
    /* and back out, so the footer gets its hearts */
    rgba(253, 242, 244, .86)  calc(100% - 24vh),
    rgba(253, 242, 244, 0)    100%
  );
}

/* ── gallery ────────────────────────────────────────────── */

.gallery {
  padding: clamp(64px, 10vh, 128px) clamp(20px, 5vw, 72px) clamp(48px, 7vh, 88px);
}

.shots {
  max-width: var(--measure);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(18px, 2.4vw, 28px);
}

.shots__pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(18px, 2.4vw, 28px);
}

.shot { margin: 0; }

.shot a {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: 10px;
}

.shot img {
  width: 100%;
  height: auto;
  border-radius: 10px;
  background: var(--white);
  box-shadow: 0 0 0 1px rgba(196, 130, 146, .26),
              0 18px 40px -30px rgba(140, 80, 95, .5);
  transition: box-shadow var(--dur) var(--ease);
}

/*
 * Nothing moves over the product photographs. The image is what the
 * visitor came to look at; the response is a firmer edge, not a lift.
 */
.shot a:hover img,
.shot a:focus-visible img {
  box-shadow: 0 0 0 1px var(--accent-text),
              0 18px 40px -30px rgba(140, 80, 95, .5);
}

.shot figcaption {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
  padding: 14px 4px 0;
}

.shot h3 { margin: 0; font-size: clamp(16px, .6vw + 14px, 19px); }
.shot .meta { font-size: 13.5px; color: var(--ink-soft); }

.shot .go {
  margin-left: auto;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent-text);
  white-space: nowrap;
}

/* ── catalog ────────────────────────────────────────────── */

.catalog {
  padding: clamp(56px, 9vh, 110px) clamp(20px, 5vw, 72px) clamp(36px, 5vh, 56px);
}

.grid {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: clamp(16px, 1.8vw, 22px);
}

/*
 * The whole card is the link — image, title, counts and swatches all sit
 * inside the anchor, so there is one large target rather than a small
 * text link beside a decorative image.
 *
 * The card is defined by a rose edge rather than a drop shadow. Nineteen
 * shadowed rounded rectangles read as a stock component grid; a tinted
 * hairline on white reads as a printed card, and it lets the image go
 * fully to the card's edge instead of floating inside a soft blur.
 */
.card {
  display: block;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
  background: var(--white);
  color: inherit;
  text-decoration: none;
  border: 1px solid rgba(196, 130, 146, .28);
  transition: border-color var(--dur) var(--ease),
              background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}

.card:hover,
.card:focus-visible {
  border-color: var(--accent-text);
  transform: translateY(-2px);
}

.card img {
  width: 100%;
  aspect-ratio: 460 / 303;
  object-fit: cover;
  background: var(--ground-1);
  /* A hairline under the image instead of a gap, so the picture reads as
     part of the card rather than pasted onto it. */
  border-bottom: 1px solid rgba(196, 130, 146, .2);
}

.card__body { padding: 14px 15px 16px; }
.card h3 { margin: 0 0 3px; font-size: 15.5px; }

.card__meta {
  margin: 0;
  font-size: 13px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/*
 * Swatches are factual colourway data and nothing else: one dot per
 * colour the set was actually released in. They carry no narrative.
 */
.ways {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 11px 0 0;
  padding: 0;
  list-style: none;
}

.ways li {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--fill);
  box-shadow: inset 0 0 0 1px rgba(90, 53, 64, .18);
}

.grid__all {
  max-width: var(--measure);
  margin: clamp(18px, 3vh, 28px) auto 0;
  text-align: center;
  font-size: 15px;
}

/* Inline links get a real target. At their natural line height these
   measured 18–22px tall, under the 24px minimum. */
.grid__all a {
  display: inline-block;
  padding: 11px 10px;
}

/* ── footer ─────────────────────────────────────────────── */

/*
 * The footer paints nothing either — the wash has already faded out above
 * it, which is what brings the hearts back.
 */
.footer {
  /* Was leaving ~200px of empty paper between the last card and the
     wordmark, which read as the page having run out rather than ended. */
  padding: clamp(64px, 9vh, 120px) clamp(20px, 5vw, 64px) clamp(48px, 6vh, 76px);
  text-align: center;
}

/*
 * The wordmark cutout, not banner.jpg — the banner carries its own
 * heart-tiled white ground and renders as a rectangle over the pink.
 *
 * --fw is the box width; the artwork's alpha bounds inside its square
 * canvas are y 0.4097 to 0.5654, so the crop is 17.6% of --fw tall (the
 * measured 15.6% plus a little air) pulled up by 40%. The visible
 * wordmark ends up about 224px wide.
 */
.footer__mark {
  --fw: min(400px, 70vw);
  position: relative;
  width: var(--fw);
  height: calc(var(--fw) * .176);
  margin: 0 auto;
  overflow: hidden;
}

.footer__mark img {
  position: absolute;
  left: 0;
  top: calc(var(--fw) * -.4);
  width: 100%;
  height: auto;
}

/*
 * The wordmark, the links and the sign-off are one cluster, not three
 * stacked items. 56px sits inside the 48-72px the composition wants.
 */
.footer__links {
  /* Measured to the links' box; their own 11px of padding puts the text
     around 60px below the wordmark, inside the intended range. */
  margin-top: 48px;
  display: flex;
  flex-wrap: wrap;
  gap: 2px 18px;
  justify-content: center;
}

.footer__links a {
  display: inline-block;
  padding: 11px 8px;
  font-size: 14.5px;
}

.footer__signoff {
  margin: 10px 0 0;
  color: var(--accent-text);
  font-size: 15px;
}

/* ── entrance ───────────────────────────────────────────── */

/*
 * The only motion on the page: sections settle in once, on first sight.
 * Not scroll-linked — it plays and finishes.
 *
 * The hidden state is scoped to .js-reveal, which main.js puts on <html>
 * only once it has an IntersectionObserver ready. If scripting fails, or
 * the observer never fires, the content is simply visible: nothing on
 * this page depends on JS to be readable.
 */
.js-reveal .reveal {
  opacity: 0;
  transform: translateY(14px);
}

.js-reveal .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .reveal,
  .reveal.is-in { opacity: 1; transform: none; transition: none; }

  .button,
  .button:hover,
  .button:focus-visible,
  .card,
  .card:hover,
  .card:focus-visible,
  .shot img,
  .shot a:hover img,
  .shot a:focus-visible img { transform: none; transition: none; }

  .button--quiet,
  .button--quiet:hover,
  .button--quiet:focus-visible { transform: none; transition: none; }
}

@media (max-width: 620px) {
  .footer__links { margin-top: 34px; }
  .shots__pair { grid-template-columns: 1fr; }
  .shot .go { margin-left: 0; }
}
