/* Article detail. Header/footer,
   .chip pills and .stories/.story-card are shared with journal.css/
   shop.css/product.css. No hero of its own — the entry opens with its
   title, and any photo is an image block placed wherever the editor
   wants it. .product__back gives it the same sticky back arrow as a
   shop item. */

/* no .page top padding here — the sticky back arrow sits flush below
   the header instead */
.page.article {
  padding-top: 0;
}

.article__categories {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

/* .product__back's own gutter+1% left padding assumes it sits outside
   .page (as on the product page) — here it's a child of .page, which
   already applies the gutter, so that would double up. 1% is then the
   only extra inset needed from .page's own left edge. */
.article > .product__back {
  padding-left: 1%;
}

/* article's own categories read as tags, not an active filter — shown
   colored at rest instead of .chip's default white-until-hover/current */
.article__categories .chip {
  background: var(--chip-color);
}

/* Full-bleed past .page's gutter: percentage margins can't cancel the
   gutter's own percentage padding pixel-for-pixel, so 100vw + centering
   transform sidesteps it entirely. */
.article__image--full,
.article__gallery-wrap,
.article__video {
  /* +2px covers subpixel rounding on the centering transform; overflow-x:clip crops the overshoot. */
  width: calc(100vw + 2px);
  margin-left: 50%;
  transform: translateX(-50%);
}

.article__title {
  margin-top: 1rem;
  margin-bottom: 1rem;
  font-size: var(--text-display); /* 48px */
  font-weight: var(--weight-medium);
  font-style: italic;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: rgba(178, 0, 107, 0.89); /* one-off */
}

/* mobile stacks the two related sections exactly as it did before the
   desktop pairing wrapper was added */
/* Related Products reuses shop.css's .products as-is; its base margin:0
   assumes sitting right at .page's top (the shop listing) — here it's
   mid-page after a heading, same scoped override as product.css's own
   .product .products. */
.article .products {
  margin-top: 1.5rem;
}

/* .blocks-body / .block-text: shared block-content spacing rules, now
   in base.css (also used by the legal pages) */

/* Panel width choice (blocks/image.yml). Normal is the flow width (the
   text column on desktop); large breaks out to the page's content area;
   full bleeds edge to edge with the rule above. */
.article__image {
  margin-block: 2rem;
}

.article__image--large {
  /* the content area, not the narrower text measure */
  width: 100%;
  max-width: none;
}

/* only the bleeding variant needs its caption pulled back into the gutter */
.article__image--full figcaption {
  padding-inline: var(--gutter);
}

.article__image img {
  width: 100%;
}

.article__image figcaption {
  margin-top: 0.5rem;
  font-size: var(--text-small);
  font-weight: var(--weight-light);
  font-style: italic;
}

/* Same continuous-drift slider as the shop/product galleries, driven by
   js/scrub-strip.js; @keyframes product-slide-scroll (product.css) is the no-JS fallback. */
.article__gallery-wrap {
  position: relative; /* anchors the slider-controls overlay */
}

/* Panel per block (gallery.yml → Shown on): a gallery can opt out of one
   side; the slider inits on first reveal (product-slider.js), so a
   hidden one never bakes zero sizes */
@media (max-width: 71.9375rem) {
  .article__gallery-wrap--desktop-only {
    display: none;
  }
}

@media (min-width: 72rem) {
  .article__gallery-wrap--mobile-only {
    display: none;
  }
}

.article__gallery {
  position: relative;
  overflow: hidden;
  cursor: grab;
  aspect-ratio: 1 / 1;
}

.article__gallery.is-dragging {
  cursor: grabbing;
}

.article__gallery-track {
  display: flex;
  height: 100%;
  touch-action: pan-y;
  animation: product-slide-scroll 30s linear infinite;
}

/* js/scrub-strip.js splits the track's two photo sets into their own
   .scrub-strip__group wrappers (position set inline by the JS) so they
   can relay past each other independently. */
.article__gallery-track .scrub-strip__group {
  display: flex;
  height: 100%;
  touch-action: pan-y;
  width: max-content; /* shrink-to-fit — getBoundingClientRect() must report real content width, not the viewport's */
}

.article__gallery-slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* aspect-ratio directly on the iframe is the current standard for
   responsive video embeds (the old padding-bottom-percentage hack isn't
   needed with modern browser support) */
.article__video iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: none;
}

.article__video figcaption {
  margin-top: 0.5rem;
  padding-inline: var(--gutter); /* video itself bleeds full-width; the caption text stays readable within the normal gutter */
  font-size: var(--text-small);
  font-weight: var(--weight-light);
  font-style: italic;
}

/* ============================================================
   Desktop. The hero fills the screen under the header instead of
   running its mobile 3:4 down the full viewport width.
   ============================================================ */

@media (min-width: 72rem) {
  /* 16px — a fifth off the listing chips' 20px. Everything else in the
     pill is em-based, so the whole thing scales with this one value. */
  .article__categories .chip {
    font-size: var(--text-ui);
  }

  /* 57.6px — the display token plus a fifth; off the token scale, whose
     ladder tops out at 48px. Margins carry a tenth more air than
     mobile's 1rem. */
  .article__title {
    margin-top: 1.1rem;
    margin-bottom: 1.1rem;
    max-width: var(--text-measure); /* don't run wider than the body column below */
    font-size: 3.6rem;
  }

  /* One measure for the text column and the images that match it: 50em
     at the 17px body below. The cap is on the text blocks, not
     .blocks-body — the full-width blocks centre themselves on their
     container, so narrowing the container would push them off-centre. */
  .article {
    --text-measure: 53.125rem;
  }

  /* Body copy at 17px regular (off the token scale — nearest tokens are
     16px and 20px), measured ~15 words a line */
  .article .block-text {
    max-width: var(--text-measure);
    font-size: 1.0625rem;
    font-weight: var(--weight-regular);
  }

  /* a multi-column block gets more than the single-column measure — but
     capped so each column itself stays at the body measure on wide
     screens (uncapped, a cols-2 block hit ~140 characters a line) */
  .article .block-text--cols-2 { max-width: calc(2 * var(--text-measure) + var(--space-4)); }
  .article .block-text--cols-3 { max-width: calc(3 * var(--text-measure) + 2 * var(--space-4)); }
  .article .block-text--cols-4 { max-width: calc(4 * var(--text-measure) + 3 * var(--space-4)); }

  .article__image--normal {
    max-width: var(--text-measure);
  }

  /* video stays inside the content column instead of mobile's full
     bleed — a 16:9 iframe across a wide window is a cinema wall */
  .article__video {
    width: 100%;
    margin-left: 0;
    transform: none;
  }

  .article__video figcaption {
    padding-inline: 0; /* the gutter inset was for the bleeding variant */
  }

  /* the full-bleed carousel would otherwise run a square 1:1 across the
     whole window — capped at 60% of the viewport height */
  .article__gallery {
    height: 60svh;
    aspect-ratio: auto;
  }

  /* Each slide is a viewport-wide panel on mobile, so a shorter band only
     cropped it harder. Here width follows the band's height at the
     photo's own proportions: the pictures actually shrink, and several
     ride the strip at once. cover, not contain — the computed box misses
     the photo's exact ratio by a rounding pixel, which contain shows as a
     white sliver between slides. */
  .article__gallery-slide {
    flex: 0 0 auto;
    width: auto;
    object-fit: cover;
  }
}
