/* Reusable page sections. Named by shape, not by the content that first
   needed them, so they carry over to any page. */

#composed {
  margin: 0 auto 100px auto;
}
#composed .b {
  max-width: 1240px;
  margin: 0 auto;
  padding: 70px 40px;
}
/* Full-bleed sections escape the page's side margins. */
#composed .b-hero {
  max-width: none;
  padding: 0;
  margin-left: calc(-1 * var(--page-gutter));
  margin-right: calc(-1 * var(--page-gutter));
  position: relative;
}

.b-button {
  display: inline-block;
  margin-top: 26px;
  padding: 14px 30px;
  border: 1px solid var(--color-2);
  border-radius: 4px;
  color: var(--color-2);
  font-family: var(--font-family-1);
  /* Matches the body copy it sits under. At 16px it read as a footnote to the
     paragraph rather than the thing to do next. */
  font-size: var(--font-size-2);
  text-decoration: none;
}
.b-button:hover {
  background: var(--color-2);
  color: var(--color-1);
}

/* ------------------------------------------------------------------- hero */

.b-hero img {
  width: 100%;
  display: block;
  object-fit: cover;
}
.b-hero--short img { height: 40vh; }
.b-hero--tall img  { height: 62vh; }
.b-hero--full img  { height: 88vh; }
.b-hero__overlay {
  position: absolute;
  inset: auto 0 0 0;
  padding: 40px;
  text-align: center;
  background: linear-gradient(to top, rgba(11, 21, 30, 0.75), transparent);
}
.b-hero__overlay h2 {
  font-size: var(--font-size-1);
  color: var(--color-2);
}
.b-hero__overlay p {
  font-family: var(--font-family-2);
  color: var(--color-2) !important;
  margin-top: 8px;
}
.b-hero__link {
  position: absolute;
  inset: 0;
}

/* ----------------------------------------------------------------- banner */

/* The header sits over the banner rather than above it. */
header.overlay-header {
  position: absolute;
  left: var(--page-gutter);
  right: var(--page-gutter);
  top: 0;
  z-index: 5;
  border-bottom: 0;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.7);
}
/* The open mobile menu is a fullscreen overlay. global.css says so, but this
   file loads after it and the two rules have the same specificity, so without
   this the banner header's inset wins and the overlay sits 18px in from each
   side with the page showing down both edges. */
@media (max-width: 700px) {
  header.overlay-header.mobile-menu {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    text-shadow: none;
  }
}

.page-banner {
  position: relative;
  /* full bleed past the body's side margins */
  margin: 0 calc(-1 * var(--page-gutter));
  overflow: hidden;
}
.page-banner img {
  width: 100%;
  display: block;
  object-fit: cover;
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--fade, 1.5s) ease-in-out;
}
/* A painting should not come away from the page onto the desktop with a
   drag. WebKit only honours the property; Firefox only the draggable
   attribute in the markup, so both are set. Neither stops Save Image As —
   nothing in a browser does. */
.page-banner img,
.b-slideshow img {
  -webkit-user-drag: none;
  user-select: none;
}
/* first image is in flow so the banner keeps its height */
.page-banner img:first-of-type {
  position: relative;
}
.page-banner img.is-active {
  opacity: 1;
}
.page-banner--short img { height: 52vh; max-height: 560px; }
.page-banner--tall img  { height: 74vh; max-height: 820px; }
.page-banner--full img  { height: 100vh; }

/* darkens just enough behind the nav for the links to stay legible */
.page-banner::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 220px;
  background: linear-gradient(to bottom, rgba(11, 21, 30, 0.65), transparent);
  z-index: 2;
  pointer-events: none;
}

/* artwork title, tucked into the corner over the image */
.page-banner__captions {
  position: absolute;
  left: 30px;
  bottom: 24px;
  z-index: 3;
  height: 1.6em;
}
/* Every caption sits in the same spot and only the active one is faded up.
   Transparent is not gone, though: an invisible caption still takes clicks
   and still takes tab focus, and the later ones stack on top — so clicking
   the caption you could see followed the link of one you could not.

   pointer-events does the real work, because it flips with the class and so
   cannot be caught out by timing. visibility then also takes the inactive
   captions out of the tab order and the accessibility tree; it is switched
   with no duration but delayed to the end of the fade, so the outgoing
   caption is still there to be seen while it fades. */
.page-banner__captions span {
  position: absolute;
  left: 0;
  bottom: 0;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--fade, 1.5s) ease-in-out,
              visibility 0s linear var(--fade, 1.5s);
  font-family: var(--font-family-1);
  font-size: var(--font-size-8);
  color: var(--color-2);
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.9);
}
.page-banner__captions span.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity var(--fade, 1.5s) ease-in-out,
              visibility 0s linear;
}
.page-banner__captions a {
  color: var(--color-2);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.4);
}
.page-banner__captions a:hover {
  border-bottom-color: var(--color-2);
}

@media (prefers-reduced-motion: reduce) {
  .page-banner img,
  .page-banner__captions span {
    transition: none;
  }
}

@media (max-width: 700px) {
  /* A phone screen is tall and narrow, so the same fraction of it buys far
     more banner and pushes the first section off the bottom. Full screen is
     left alone — that one is asking for the whole screen on purpose. */
  .page-banner--short img { height: 34vh; }
  .page-banner--tall img  { height: 46vh; }

  .page-banner__captions {
    left: 18px;
    bottom: 16px;
  }
  .page-banner__captions span {
    font-size: var(--font-size-4);
  }
}

/* -------------------------------------------------------------- slideshow */

#composed .b-slideshow {
  /* Full bleed left and right, but the image itself stays capped so it does
     not become absurdly large on a wide monitor. */
  max-width: none;
  padding: 0;
  margin-left: calc(-1 * var(--page-gutter));
  margin-right: calc(-1 * var(--page-gutter));
  position: relative;
  overflow: hidden;
}
.b-slideshow img {
  width: 100%;
  max-width: 1800px;
  margin: 0 auto;
  display: block;
  object-fit: cover;
  /* Stack them so one can dissolve into the next. */
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--fade, 1.5s) ease-in-out;
}
.b-slideshow img.is-active {
  opacity: 1;
}
/* The first image is in flow so the section keeps its height. */
.b-slideshow img:first-of-type {
  position: relative;
}
.b-slideshow--short img { height: 45vh; max-height: 520px; }
.b-slideshow--tall img  { height: 68vh; max-height: 760px; }
.b-slideshow--full img  { height: 92vh; max-height: 1000px; }

.b-slideshow__overlay {
  position: absolute;
  inset: auto 0 0 0;
  padding: 40px;
  text-align: center;
  background: linear-gradient(to top, rgba(11, 21, 30, 0.75), transparent);
  z-index: 2;
}
.b-slideshow__overlay h2 {
  font-size: var(--font-size-1);
  color: var(--color-2);
}
.b-slideshow__link {
  position: absolute;
  inset: 0;
  z-index: 3;
}

/* Someone who has asked for less motion gets the first image, held still. */
@media (prefers-reduced-motion: reduce) {
  .b-slideshow img {
    transition: none;
  }
}

/* ------------------------------------------------------------------- text */

.b-text--center { text-align: center; }
.b-text h2 {
  font-size: var(--font-size-1);
  color: var(--color-5);
  margin-bottom: 18px;
}
.b-text__body {
  /* 34 lines-worth of the reading size. It has to be spelled out rather than
     written in em: the wrapper does not carry the paragraph's font-size, so an
     em here measured against the inherited 16px and came out a third narrow. */
  max-width: calc(34 * var(--font-size-2));
  margin: 0 auto;
}
/* Body copy matches the about and visit pages rather than inheriting the
   smaller default. */
.b-text__body p,
.b-media-text__text p {
  font-size: var(--font-size-2);
  line-height: 35px;
}
.b-text--left .b-text__body { margin-left: 0; }

/* ------------------------------------------------------------------ cards */

.b-cards h2 {
  font-size: var(--font-size-1);
  color: var(--color-5);
  margin-bottom: 30px;
}
.b-cards__grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), 1fr);
  gap: 26px;
}
.b-cards__grid a {
  text-decoration: none;
  color: var(--color-2);
  display: block;
}
.b-cards__grid img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  margin-bottom: 12px;
}
.b-cards__arrow { color: var(--color-4); }
.b-cards__grid a:hover .b-cards__arrow { color: var(--color-5); }

/* ------------------------------------------------------------- media+text */

.b-media-text {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
}
.b-media-text--left .b-media-text__text  { order: 2; }
.b-media-text--left .b-media-text__media { order: 1; }
.b-media-text h2 {
  font-size: var(--font-size-1);
  color: var(--color-5);
  margin-bottom: 18px;
}
.b-media-text__media img {
  width: 100%;
  display: block;
}

/* ------------------------------------------------------------------- shop */

.b-shop h2 {
  font-size: var(--font-size-2);
  color: var(--color-5);
  margin-bottom: 26px;
}
.b-shop__grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(var(--cols, 4), 1fr);
  gap: 30px 24px;
}
.b-shop__item a {
  text-decoration: none;
  color: var(--color-2);
  display: block;
}
.b-shop__item figure {
  position: relative;
  margin-bottom: 10px;
}
.b-shop__item img {
  /* Whole image, natural proportions — product shots are framed pieces and
     puzzles of different shapes, and cropping them to a square cuts into the
     artwork. */
  width: 100%;
  height: auto;
  display: block;
}
.b-shop__item.is-sold-out img { opacity: 0.45; }
.b-shop__badge {
  position: absolute;
  top: 10px;
  left: 10px;
  background: var(--color-1);
  color: var(--color-2);
  font-family: var(--font-family-2);
  font-size: var(--font-size-3);
  padding: 4px 9px;
}
.b-shop__title {
  display: block;
  font-family: var(--font-family-2);
  font-size: var(--font-size-4);
  line-height: 1.4;
}
.b-shop__price {
  display: block;
  font-family: var(--font-family-2);
  font-size: var(--font-size-4);
  color: var(--color-7);
  margin-top: 4px;
}
.b-shop__empty {
  font-family: var(--font-family-2);
  color: var(--color-7) !important;
}

/* ------------------------------------------------------------------ award */

/* A centred plaque rather than a full-width band: the section only centres
   the box, and the box is as wide as the words inside it. */
#composed .b-award {
  padding: 40px;
  display: flex;
  justify-content: center;
}
.b-award__panel {
  display: flex;
  flex-flow: column nowrap;
  align-items: center;
  gap: 14px;
  text-align: center;
  border: 1px solid var(--color-4);
  border-radius: 6px;
  padding: 38px 52px;
  max-width: 30em;
}
.b-award__badge {
  width: 120px;
  margin: 0;
}
.b-award__badge img {
  width: 100%;
  display: block;
}
.b-award__title {
  font-family: var(--font-family-1);
  font-size: var(--font-size-6);
  line-height: 1.25;
  color: var(--color-6);
  margin-bottom: 0;
}
.b-award__source {
  font-family: var(--font-family-2);
  font-size: var(--font-size-8);
  line-height: 1.5;
  color: var(--color-2);
  margin-bottom: 0;
}
a.b-award__panel {
  text-decoration: none;
  color: inherit;
}
a.b-award__panel:hover {
  border-color: var(--color-2);
}
.b-award__link {
  font-family: var(--font-family-2);
  font-size: var(--font-size-4);
  color: var(--color-7);
  text-decoration: underline;
  text-underline-offset: 3px;
}
a.b-award__panel:hover .b-award__link {
  color: var(--color-2);
}
/* The gap already spaces these; the paragraph rhythm would double it. */
.b-award__panel > * + * {
  margin-top: 0;
}

/* ---------------------------------------------------------------- reviews */

.b-reviews h2 {
  font-size: var(--font-size-1);
  color: var(--color-5);
  margin-bottom: 30px;
}
.b-reviews__grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 30px;
}
.b-reviews__grid li {
  border: 1px solid var(--color-3);
  padding: 26px;
}
.b-reviews blockquote {
  font-family: var(--font-family-2);
  font-size: var(--font-size-8);
  line-height: 1.6;
  margin: 0 0 12px 0;
}
.b-reviews cite {
  font-family: var(--font-family-2);
  font-size: var(--font-size-4);
  color: var(--color-7);
  font-style: normal;
}

/* ----------------------------------------------------------------- mobile */

@media (max-width: 900px) {
  #composed .b { padding: 46px 20px; }
  .b-media-text {
    grid-template-columns: 1fr;
    gap: 26px;
  }
  .b-media-text--left .b-media-text__text,
  .b-media-text--left .b-media-text__media { order: initial; }
  .b-cards__grid  { grid-template-columns: repeat(2, 1fr); }
  .b-shop__grid   { grid-template-columns: repeat(2, 1fr); }
  .b-reviews__grid { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
  /* Together with the smaller page gutter this leaves 24px each side rather
     than 38px — the sections were giving up a fifth of a phone screen. */
  #composed .b { padding: 42px 12px; }
}

@media (max-width: 560px) {
  .b-award__panel { padding: 30px 24px; }
  .b-award__badge { width: 96px; }
}

/* ------------------------------------------------------------------- map */

.b-map__canvas {
  /* MapLibre needs a height on the container or it renders nothing at all. */
  height: 420px;
  width: 100%;
  border: 1px solid var(--color-3);
  background: var(--color-1);
}
.b-map__fallback {
  padding: 20px;
  font-family: var(--font-family-2);
  color: var(--color-4);
}
.b-map__marker {
  width: 54px;
  height: 54px;
  border: 2px solid var(--color-5);
  overflow: hidden;
  cursor: default;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
.b-map__marker img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.b-map__marker--dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-5);
}
/* MapLibre's own chrome, toned down to match the page. */
.b-map .maplibregl-ctrl-group {
  background: var(--color-8);
  border: 1px solid var(--color-3);
}
.b-map .maplibregl-ctrl-group button + button { border-top-color: var(--color-3); }
.b-map .maplibregl-ctrl-group button span { filter: invert(1) opacity(0.7); }
.b-map .maplibregl-ctrl-attrib {
  background: rgba(11, 21, 30, 0.75);
  font-size: 10px;
}
.b-map .maplibregl-ctrl-attrib a { color: var(--color-4); }

/* ------------------------------------------------------- related artwork */

/* Every other block styles its own h2; this one was inheriting only the
   global colour, so the heading sat straight on top of the thumbnails. */
.b-related h2 {
  font-size: var(--font-size-1);
  /* global.css sets h2 colour with !important, so this has to answer in kind */
  color: var(--color-2) !important;
  margin-bottom: 30px;
}
.b-related__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 22px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.b-related__grid a {
  text-decoration: none;
  color: var(--color-2);
  display: block;
}
.b-related__grid figure {
  margin: 0 0 10px;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--color-8);
}
.b-related__grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.b-related__title {
  font-family: var(--font-family-2);
  font-size: var(--font-size-4);
}
.b-related__grid a:hover .b-related__title { color: var(--color-5); }

@media (max-width: 700px) {
  .b-related__grid { grid-template-columns: repeat(2, 1fr); }
  .b-map__canvas { height: 300px; }
}
