/* Contemporaryheadshot.com — redesign prototype
   Home page. Faithful refresh of the live layout: same sections in the same order,
   modernised type, spacing and colour, and the images that were broken on the live
   site rendering properly.

   Type: the live site sets headings in Cardo (a serif) and body copy in a neutral
   grotesque. Both are substituted here with system stacks so the prototype previews
   offline; swapping in the real webfonts is a one-line change to --font-display /
   --font-body. */

:root {
  /* Colour — a restrained monochrome with a warm off-white, plus the black bands */
  --ink: #111111;
  --ink-soft: #454545;
  --muted: #7d766c;
  --paper: #ffffff;
  --cream: #f6f4f1;
  --band: #0d0d0d;
  --on-band: #f4f2ef;
  --on-band-muted: #a09a92;
  --rule: rgba(17, 17, 17, 0.14);
  --rule-band: rgba(244, 242, 239, 0.2);

  /* Type */
  --font-display: Georgia, "Times New Roman", "Liberation Serif", serif;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --step--1: 0.875rem;
  --step-0: 1.0625rem;
  --step-1: clamp(1.125rem, 0.9rem + 0.7vw, 1.375rem);
  --step-2: clamp(1.5rem, 1.1rem + 1.6vw, 2.125rem);
  --step-3: clamp(1.875rem, 1.2rem + 2.6vw, 3rem);

  /* Space */
  --gap: clamp(1.5rem, 3vw, 2.5rem);
  /* The air between sections. Steph, 2026-10-09, on the business page: *"the space between sections is
     still too big … Can you reduce the space and make it equal between sections ?"* — every section
     carries this padding top and bottom, so two neighbours always add up to twice this figure: the seam
     is the same everywhere by construction. Halved from `clamp(3.5rem, 7vw, 7rem)` (7rem = 112px at
     1707, so a 224px seam) to this (3.5rem = 56px, so a 112px seam). The blocks that carry padding of
     their own — the quote band, the closing strip, the page head — were brought onto the same figure at
     the same time, or they would have kept their own seam. */
  --section-y: clamp(2rem, 3.5vw, 3.5rem);
  --wrap: 74rem;
  --pad: clamp(1.25rem, 4vw, 2.5rem);
}

*,
*::before,
*::after { box-sizing: border-box; }

/* An element with the hidden attribute is hidden, whatever display a class sets on it. Without
   this, `[data-booker-days] { display: grid }` wins over the browser's own `[hidden]` rule and an
   empty section shows as an empty box. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; height: auto; }

a { color: inherit; }

h1, h2, h3, h4 { margin: 0; font-weight: 400; line-height: 1.2; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute;
  left: 0; top: -100%;
  z-index: 20;
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: #fff;
  text-decoration: none;
}
.skip-link:focus { top: 0; }

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--pad);
}

/* The gallery wall takes the width of the screen (2026-10-08). The reference gallery it was rebuilt
   from keeps the photographs to a 4vw margin on every side rather than holding them to the site's
   reading width — the wall is the picture, and at his 1707px window that is the difference between
   322px tiles and the 478px ones the reference has. Only the wall's own band uses this. */
.wrap--wide {
  max-width: none;
  padding: 0 4vw;
}

/* ---------- Header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  /* White header with the artwork in its own black (Steph's request 2026-09-26) —
     the same light treatment the live site uses. The hairline keeps it from merging
     with the white page when it is stuck over a light section. */
  background: var(--paper);
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 6.5rem;   /* 104px, the height of the header on the live site */
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  text-decoration: none;
}

/* The logo is black artwork on transparency: it stays black in the white header and
   is inverted only for the black footer band. */
.brand__logo,
.footer__logo {
  height: auto;
}

.footer__logo { filter: brightness(0) invert(1); }

/* 5.625rem = 90px, the size of the logo on the live site — it is what sets the
   header's height (104px there, and the same here). The footer logo stays small. */
.brand__logo { width: 5.625rem; }
.footer__logo { width: 2.75rem; }

.brand__name {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  letter-spacing: 0.01em;
}

.nav {
  display: flex;
  align-items: center;
  gap: 1.75rem;
}

.nav__list {
  display: flex;
  gap: 1.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav a {
  text-decoration: none;
  font-size: 0.8125rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.nav__list a {
  padding-bottom: 0.2rem;
  border-bottom: 1px solid transparent;
}

.nav__list a:hover { border-bottom-color: var(--ink); }

/* The page you are on carries the underline the hover uses, so the header answers "where am I?"
   rather than only telling a screen reader. */
.nav__list a[aria-current='page'] { border-bottom-color: var(--ink); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-block;
  padding: 0.8rem 1.6rem;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.btn--solid,
.btn:hover {
  background: var(--ink);
  color: #fff;
}

/* The header's Book button: a dark outline, since the header is now white. */
.btn--ghost {
  border-color: rgba(17, 17, 17, 0.35);
  color: var(--ink);
}

/* Two buttons on one line wrap onto two rather than running off a phone. */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

.btn--ghost:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

/* ---------- Sliders (hero and testimonials) ---------- */

.hero__viewport { --visible: 5; }   /* five portraits across, their natural shape on a wide screen */

/* A band holding four portraits says so, instead of leaving the fifth slot empty: an
   unfilled slot is a black strip down the right-hand side of the page. The narrow-screen
   counts below still take over, so this only ever sets the wide-screen number. */
.hero__viewport--4 { --visible: 4; }
.viewport { --visible: 3; }         /* testimonial strips stay three across */

.hero__track,
.testimonials {
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}

.hero__track::-webkit-scrollbar,
.testimonials::-webkit-scrollbar { display: none; }

.hero__slide,
.testimonial {
  flex: 0 0 calc(100% / var(--visible));
  scroll-snap-align: start;
}

.hero__slide img {
  width: 100%;
  height: 100%;
  aspect-ratio: 2 / 3;
  /* The live site's banner measures 571px tall at every window width (its own block is
     capped at 856px wide). Cap ours at the same height, so it stops growing on a wide
     screen instead of taking over the page. Below ~1140px the aspect ratio above wins. */
  max-height: 570px;
  object-fit: cover;
  /* The cap crops the 2:3 portrait from the bottom only, so no head loses headroom. */
  object-position: 50% 0;
}

/* Full-bleed strip of portraits at the top of the page */
.hero { background: var(--band); }
.hero__viewport { position: relative; }

.dots {
  display: flex;
  justify-content: center;
  gap: 0.6rem;
  padding: 1.25rem var(--pad);
}

.dots__dot {
  width: 26px;
  height: 3px;
  padding: 0;
  border: 0;
  background: rgba(17, 17, 17, 0.25);
  cursor: pointer;
}

.hero .dots__dot { background: rgba(244, 242, 239, 0.35); }

.dots__dot[aria-selected="true"] { background: var(--ink); }
.hero .dots__dot[aria-selected="true"] { background: var(--on-band); }

/* The credit line under the article's banner: the strip itself carries no captions, so this is where
   the photographers and the years stay visible. Smaller and quieter than the lede above it. */
.credit-line {
  margin-top: 0.75rem;
  font-size: var(--step--1);
  color: var(--ink-soft);
}

/* ---------- Sections ---------- */

.section { padding: var(--section-y) 0; }
.section--tint { background: var(--cream); }

.section__head {
  max-width: 44rem;
  margin: 0 auto clamp(2.5rem, 5vw, 4rem);
  text-align: center;
}

.display {
  font-family: var(--font-display);
  font-size: var(--step-3);
  letter-spacing: -0.01em;
}

.lede {
  margin-top: 0.9rem;
  color: var(--muted);
  font-size: var(--step-1);
}

.kicker-h {
  font-family: var(--font-body);
  font-size: 0.8125rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin-bottom: 1.25rem;
}

/* Three columns: the circles, headings and copy of the live intro block.
   Centred, as the live site has it: image, heading and the paragraph under it. */
.cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap);
}

/* Only the circle-marked columns are centred — the pricing columns on the team page
   and the partner-logo cells on Faces of Resilience share the .col class and are not
   part of this pattern. */
.col:has(.col__mark) { text-align: center; }

.col__mark {
  width: 70px;
  height: 70px;
  border-radius: 50%;
  object-fit: cover;
  margin: 0 auto 1.5rem;   /* centred: text-align does not move a block-level image */
}

.col__title {
  font-family: var(--font-display);
  font-size: var(--step-1);
  margin-bottom: 0.6rem;
}

.col p {
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

/* Picture + copy, as on the live site (actor and business sections) */
.media {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(1.75rem, 5vw, 4.5rem);
  align-items: center;
}

.media--reverse .media__figure { order: 2; }
.media--reverse .media__body { order: 1; }

/* The picture keeps the smaller share whichever side it sits on. Without this line the two rules
   above only move the picture into the wider column, and the business picture renders half as big
   again as the actor one — 602 × 903 against 430 × 645 at 1707 px, with its copy squeezed into the
   narrow column at the same time. */
.media--reverse { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }

.media__figure { margin: 0; }

.media__figure img {
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
}

.media__body p { color: var(--ink-soft); }

/* ---------- Quote band ---------- */

.quote {
  background: var(--band);
  color: var(--on-band);
  /* On the section figure rather than its own (was clamp(3.5rem, 8vw, 6.5rem)), so the seams either side
     of the band match the rest of the page. 2026-10-09. */
  padding: var(--section-y) 0;
  text-align: center;
}

.quote blockquote { margin: 0; }
.quote__inner { max-width: 52rem; }

.quote__text {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.375rem, 1rem + 1.8vw, 2.25rem);
  line-height: 1.35;
  margin: 0 0 1.75rem;
}

.quote__name {
  margin: 0;
  font-size: 0.8125rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.quote__role {
  margin: 0.35rem 0 0;
  color: var(--on-band-muted);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* ---------- Newsletter ---------- */

.newsletter {
  max-width: 40rem;
  text-align: center;
}

.newsletter__form {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 2rem;
}

.newsletter__form input {
  flex: 1 1 18rem;
  min-width: 0;
  padding: 0.8rem 1rem;
  border: 1px solid var(--rule);
  background: var(--paper);
  font: inherit;
  font-size: 0.9375rem;
}

.newsletter__note {
  flex: 1 1 100%;
  margin: 0.5rem 0 0;
  color: var(--muted);
  font-size: 0.8125rem;
}

/* Forms — the enquiry form and the newsletter sign-ups. Both POST to this site's own API
   (tools/forms-api/), so the record is created server-side; site.js only shows the reply. */
.form {
  display: grid;
  gap: 1rem;
  text-align: left;
}
.form__row {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.form__field {
  display: grid;
  gap: 0.35rem;
}
.form__field > label {
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.form__field input,
.form__field select,
.form__field textarea {
  width: 100%;
  min-width: 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 0.9375rem;
}
.form__field textarea {
  min-height: 7rem;
  resize: vertical;
}
.form__field input:focus,
.form__field select:focus,
.form__field textarea:focus {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
}
.form__consent {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.65rem;
  align-items: start;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.form__consent input {
  width: 1.15rem;
  height: 1.15rem;
  margin: 0.1rem 0 0;
}
.form__optional {
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.6875rem;
  color: var(--muted);
}
.form__hint {
  margin: 0;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.55;
}
.form__note {
  margin: 0;
  font-size: 0.875rem;
  color: var(--ink-soft);
}
.form__note--error {
  color: #8a2318;
}
.form__honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.form button[type="submit"] {
  justify-self: start;
}
.form button[type="submit"][disabled] {
  opacity: 0.6;
  cursor: default;
}
.newsletter .form {
  grid-template-columns: 1fr;
  justify-items: stretch;
  text-align: center;
}
.newsletter .form__consent {
  text-align: left;
  max-width: 30rem;
  margin: 0 auto;
}
.newsletter .form button[type="submit"] {
  justify-self: center;
}

/* ---------- Testimonials ---------- */

.testimonial {
  /* Centred like the three-column block (Steph's request 2026-09-26); the live site
     has its testimonials left-aligned, so this is a deliberate departure, not a miss.
     Padding is symmetric now, so the centred text sits in the middle of its column. */
  padding: 0 clamp(0.75rem, 1.5vw, 1.25rem);
  text-align: center;
}

.testimonial img {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  object-fit: cover;
  margin: 0 auto 1.25rem;
}

.testimonial__name {
  font-size: 0.8125rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 0.75rem;
}

.testimonial p {
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

/* ---------- Closing strip ---------- */

/* The closing band of portraits. It carried no padding of its own, so the air above it was half the air
   between two sections; it now takes the section figure at the top and nothing at the bottom (the footer
   follows). 2026-10-09. */
.strip { padding: var(--section-y) 0 0; }

.strip__caption {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--step-2);
  text-align: center;
  padding: 0 var(--pad) clamp(2rem, 4vw, 3rem);
}

.strip__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--band);
}

.strip__row img {
  width: 100%;
  height: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

/* ---------- Footer ---------- */

.site-footer {
  background: var(--band);
  color: var(--on-band);
  padding: clamp(3rem, 6vw, 5rem) 0 2.5rem;
  font-size: 0.9375rem;
}

.footer__cols {
  display: grid;
  /* brand · Navigation · Business · Privacy · Personal Work */
  grid-template-columns: 1.4fr 1fr 1fr 1fr 1fr;
  gap: var(--gap);
}

.footer__logo { width: 3rem; }

.footer__brand {
  font-family: var(--font-display);
  margin: 1.25rem 0 0.35rem;
}

.footer__tagline {
  margin: 0;
  color: var(--on-band-muted);
  font-size: 0.875rem;
}

.footer__h {
  font-size: 0.75rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--on-band-muted);
  margin-bottom: 1rem;
}

.footer__col ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer__col li { margin-bottom: 0.6rem; }

.footer__col a { text-decoration: none; }
.footer__col a:hover { text-decoration: underline; }

.footer__blurb {
  max-width: 62ch;
  margin: clamp(2.5rem, 5vw, 4rem) 0 0;
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule-band);
  color: var(--on-band-muted);
  font-size: 0.875rem;
}

.footer__social {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin: 1.75rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.footer__social a { text-decoration: none; color: var(--on-band-muted); }
.footer__social a:hover { color: var(--on-band); }

/* ---------- Cookie notice ----------
   The site's own notice: no third-party script, and nothing is sent to Google until a visitor
   clicks Accept (assets/js/consent.js reads the answer, the head defines the loader). Dark band
   to match the footer, fixed to the bottom, and it must never widen the page on a phone. */

.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  background: var(--band);
  color: var(--on-band);
  border-top: 1px solid var(--rule-band);
  padding: clamp(1rem, 2.5vw, 1.5rem) 0;
  box-shadow: 0 -14px 44px rgba(0, 0, 0, 0.32);
}

.consent__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
}

.consent__text {
  margin: 0;
  max-width: 64ch;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--on-band-muted);
}

.consent__text a { color: var(--on-band); }
.consent__text em { font-style: normal; color: var(--on-band); }

.consent__actions {
  display: flex;
  gap: 0.75rem;
  flex-shrink: 0;
}

.consent__actions .btn {
  border-color: rgba(244, 242, 239, 0.45);
  color: var(--on-band);
  background: transparent;
  cursor: pointer;
}

.consent__actions .btn:hover,
.consent__actions .btn:focus-visible {
  background: var(--on-band);
  border-color: var(--on-band);
  color: var(--band);
}

.consent__accept {
  background: var(--on-band);
  border-color: var(--on-band);
  color: var(--band);
  font-weight: 500;
}

.consent__accept:hover,
.consent__accept:focus-visible {
  background: transparent;
  color: var(--on-band);
}

/* the footer's way back to the notice, dressed as the links around it */
.footer__col button[data-cookie-settings] {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.footer__col button[data-cookie-settings]:hover { text-decoration: underline; }

@media (max-width: 48rem) {
  .consent__row { flex-direction: column; align-items: stretch; }
  .consent__actions { flex-direction: row; }
  .consent__actions .btn { flex: 1; }
}

/* ---------- Booking page: price + scheduler ---------- */

.section--tight { padding-top: 0; }

.page-head {
  text-align: center;
  /* Kept on the same figure as every other section (was clamp(1.5rem, 3vw, 2.5rem), which made the seam
     under the page head the odd one out). 2026-10-09. */
  padding-bottom: var(--section-y);
}

.page-head .lede { max-width: 46rem; margin-left: auto; margin-right: auto; }
.page-head a { color: inherit; }

.book {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

.book__scheduler,
.panel {
  min-height: 18rem;
  padding: clamp(1.5rem, 3vw, 2.5rem);
  border: 1px solid var(--rule);
  background: var(--cream);
}

.book__scheduler p,
.panel p { color: var(--ink-soft); max-width: 40ch; }

.book__price { text-align: center; }

.price__figure {
  font-family: var(--font-display);
  font-size: clamp(3rem, 7vw, 4.5rem);
  line-height: 1;
  margin: 0 0 0.75rem;
}

.price__includes {
  font-family: var(--font-display);
  font-size: var(--step-1);
  margin: 0 0 1.75rem;
}

.price__list {
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink-soft);
  font-size: 0.9375rem;
  line-height: 1.9;
}

/* ---------- Lists on the business page ---------- */

.checklist {
  display: grid;
  gap: 0.6rem;
  max-width: 46rem;
  margin: 2rem 0;
  padding: 0;
  list-style: none;
}

.checklist li {
  position: relative;
  padding-left: 1.6rem;
  color: var(--ink-soft);
}

.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--ink);
}

.detail-list {
  max-width: 46rem;
  margin: 1.5rem 0;
}

.detail-list dt {
  margin-top: 1.1rem;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.detail-list dd {
  margin: 0.3rem 0 0;
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

/* ---------- Gallery grid ---------- */

/* ---------- The gallery: a wall of portraits, three photographs across ----------

   Steph's ask of 2026-10-08, pointing at tomtrevatt.com/actors-headshots-london: *"I would like the
   design of it to be like this page … it resizes nicely on mobile. try to recreate the same. Just
   design, no functionality change."* Measured from that page with a browser: the gallery is one
   **uniform grid** — three across on a wide screen, two on a phone (it switches at 768px), every tile
   the same 3:4 portrait whatever shape the file is (the photograph is cropped to fill it), and a 4vw
   gutter on every side. At his width that is 478×638 tiles with 68px gaps; at 390px, 179×240 with
   15.6px gaps.

   This replaces the masonry of natural shapes he asked for earlier ("masonry type, large photos"),
   which kept every photograph whole but left the rows ragged and the tiles different sizes. Here the
   rows line up and a photograph that is not 3:4 is cropped to the tile. Nothing else moved: the same
   tiles, in the same order, no script, and no lightbox (there is none on this site either way).

   His ask of the same evening: *"The separation between the photos should be thinner. Try to reduce the
   space between photos by half to start with"* — so the 4vw gutter became **2vw** here and in the
   two-across block below (68px → 34px at his width, 15.6px → 7.8px on a 390px phone).

   Then: *"still a bit too larch [large]. Can you apply the same spacing as this page:
   https://www.tomtrevatt.com/"* — the reference's **home page**, measured in a browser at five widths, keeps
   its wall at a gutter of **1.25vw**: 21px between tiles at 1707px (4 across, tiles 394×526), 18px at 1440,
   13px at 1024, 10px at 768, 5px at 390. So the gutter here is **1.25vw** too — horizontally and
   vertically the same, since the reference's rows and columns are spaced alike.

   Still a gutter, not a hairline: the gallery page he first pointed at keeps 4vw, the home page 1.25vw, so
   those are the two figures to move between with his word.

   Every image keeps its width and height attributes, so the tiles are the right shape before the
   files arrive and nothing jumps as they load — the "loads fast" half of the earlier ask, kept. */
.gallery {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25vw;
}

.gallery > * {
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: var(--cream);
}

.gallery img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------- Sponsor / partner logo row ---------- */

.logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(1.5rem, 4vw, 3rem);
}

.logos img {
  display: block;
  width: auto;
  height: auto;
  max-width: 11rem;
  max-height: 4.5rem;
  object-fit: contain;
}

/* ---------- Plates: portraits with their captions (the history article) ---------- */

.plates {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: clamp(1rem, 2.5vw, 2rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.plates img {
  display: block;
  width: 100%;
  height: auto;
}

.plates figcaption {
  margin-top: 0.6rem;
  font-size: var(--step--1);
  color: var(--ink-soft);
  text-align: center;
}

/* ---------- Long-form prose (legal pages) ---------- */

/* Long unbreakable words (the release text has "Assignment/Waiver/Agreement") are wider than a
   360px column and were pushing the whole model-release page 52px wide on a phone. break-word only
   acts when a word cannot fit its line, so ordinary prose is untouched. */
.prose {
  overflow-wrap: break-word;
  max-width: 44rem;
  margin-inline: auto;
}

.prose > * + * {
  margin-top: 1rem;
}

.prose h2 {
  font-family: var(--font-display);
  font-size: var(--step-1);
  margin: 2.5rem 0 1rem;
}

.prose h3 {
  font-family: var(--font-display);
  font-size: var(--step-0);
  margin: 2rem 0 0.75rem;
}

.prose p,
.prose li {
  color: var(--ink-soft);
}

.prose ul {
  margin: 1rem 0 0.5rem;
  padding-left: 1.25rem;
}

/* ---------- Wide screens: the band shows more portraits rather than bigger ones ---------- */

/* A portrait in the band is about 341px wide on the laptop it is judged on, and 570px tall is the
   tallest it is allowed to be — which a 2:3 photograph reaches at 380px wide. So a band of five can
   carry the full width only up to 1900px: past that the tile is wider than the photograph and
   `object-fit: cover` cuts it, keeping the top (a quarter of each portrait gone at 2560px, half of it
   at 3840px — Steph's 32" screen, 2026-10-02). The band therefore answers a wider screen by showing
   MORE of the page's portraits, not by making them bigger: every step keeps a tile between about
   341px and 430px, so the portraits stay the size they are on the laptop and the band stays the
   height it is there. Each step asks for its extra slot only where the page actually has the
   photograph (`:has(> *:nth-child(n))` counts the slides), because a slot with no photograph is a
   black strip at one end of the band. Nothing below 1900px changes, so the laptop's own five across
   is untouched. */
@media (min-width: 1900px) {
  /* five across still, up to 2050px: 380–410px tiles, so the cap has to move with them */
  .hero__slide img { max-height: 620px; }
}

@media (min-width: 2050px) {
  .hero__slide img { max-height: 640px; }
  .hero__track:has(> *:nth-child(6)) { --visible: 6; }
}

@media (min-width: 2390px) {
  .hero__slide img { max-height: 780px; }
  .hero__track:has(> *:nth-child(7)) { --visible: 7; }
}

@media (min-width: 2950px) {
  .hero__slide img { max-height: 940px; }
  .hero__track:has(> *:nth-child(8)) { --visible: 8; }
}

/* The closing strip: four portraits at the foot of the page, and the bands that hold four of their
   own. Four across is a grid, so each portrait grows with the window and by 3840px every one was
   960px wide — nearly twice the band at the top of the same page (Steph's 32" screen, 2026-10-02:
   "the 4 images banner at the bottom looks really big"). The strip keeps the band's own portrait size
   and **spreads its four across the whole width**, so what is left reads as band colour between
   portraits rather than as one gap in the middle — "happy for the images to be spaced out so it's
   easier to flex" (his second look at it, the same day). Below 1900px nothing changes: the foot of
   the page is as it is on the laptop. */
@media (min-width: 1900px) {
  .strip { background: var(--band); }
  .strip__caption { color: var(--on-band); }
  .strip__row {
    display: flex;
    justify-content: space-between;
  }
  .strip__row > li { flex: 0 0 20%; }        /* one portrait is the band's own tile: a fifth at five across */
}

@media (min-width: 2050px) {
  .strip__row > li { flex: 0 0 16.67%; }     /* a sixth at six across */
}

@media (min-width: 2390px) {
  .strip__row > li { flex: 0 0 14.29%; }     /* a seventh at seven across */
}

@media (min-width: 2950px) {
  .strip__row > li { flex: 0 0 12.5%; }      /* an eighth at eight across */
}

/* A band that holds four of its own cannot carry a 3840px screen at that size either, so it is held to
   the band's own portrait width and centred — a band stays a band: its portraits side by side, with the
   band colour either side of them rather than spaced between them. */
@media (min-width: 1900px) {
  .hero__viewport--4 .hero__track { max-width: 80%; margin-inline: auto; }
}

@media (min-width: 2050px) {
  .hero__viewport--4 .hero__track { max-width: 66.67%; }
}

@media (min-width: 2390px) {
  .hero__viewport--4 .hero__track { max-width: 57.14%; }
}

@media (min-width: 2950px) {
  .hero__viewport--4 .hero__track { max-width: 50%; }
}

/* ---------- Narrow screens ---------- */

@media (max-width: 960px) {
  .hero__viewport { --visible: 3; }
  .viewport { --visible: 2; }
  .footer__cols { grid-template-columns: 1fr 1fr; }
  .book { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  /* Two across on a phone or a narrow window, which is what the reference gallery does too — it
     switches from three to two at 768px. The gutter is 1.25vw here too, matching the reference's home
     page (measured 21px at 1707px and 5px at 390px), so the tiles stay whole numbers of pixels on any
     screen rather than shrinking with a font.
     Two classes, not one: `.cols` is set to a single column further down this same block, and a rule
     of the same weight that comes after it would win. */
  .cols.gallery {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.25vw;
  }

  .hero__viewport,
  .viewport { --visible: 1; }

  /* Phones: one portrait at a time, shown whole and sized to the screen. The box is a
     share of the viewport height instead of a fixed 570px, and object-fit: contain
     means nothing is cut off — the photograph is scaled down inside the band rather
     than cropped. (The 60vh line is the fallback for browsers without svh units.) */
  .hero__slide img {
    max-height: 60vh;
    max-height: min(60svh, 32rem);
    object-fit: contain;
  }

  .site-header__inner { flex-wrap: wrap; gap: 1rem; }
  .nav { gap: 1.25rem; }
  .nav__list { gap: 1.25rem; }

  .cols { grid-template-columns: 1fr; gap: 2.25rem; }

  .media,
  .media--reverse { grid-template-columns: 1fr; }
  .media--reverse .media__figure { order: 0; }

  /* The live site hides this band on small screens; keeping that behaviour */
  .strip__row { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__track,
  .testimonials { scroll-behavior: auto; }
}

/* Booking calendar — the site's own, not a plugin. The rules live in
   tools/forms-api/booking-config.json; booking.js paints what the API answers. */
.booker {
  display: grid;
  gap: 1.5rem;
  text-align: left;
}
.booker__types {
  border: 0;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}
.booker__legend {
  padding: 0;
  margin-bottom: 0.6rem;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.booker__type {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.9rem 1rem;
  border: 1px solid var(--rule);
  background: var(--paper);
  cursor: pointer;
}
.booker__type:hover {
  border-color: var(--ink);
}
.booker__type:has(input:checked) {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}
.booker__type input {
  margin: 0.35rem 0 0;
  accent-color: var(--ink);
}
.booker__type-body {
  display: grid;
  gap: 0.2rem;
}
.booker__type-name {
  font-family: var(--font-display);
  font-size: 1.125rem;
}
.booker__type-text {
  margin: 0;
  font-size: 0.875rem;
  color: var(--ink-soft);
}
.booker__type-meta {
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.booker__days {
  display: grid;
  gap: 0.5rem;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
}
.booker__day {
  display: grid;
  gap: 0.15rem;
  padding: 0.6rem 0.5rem;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 0.9375rem;
  text-align: center;
  cursor: pointer;
}
.booker__day:hover {
  border-color: var(--ink);
}
.booker__day.is-chosen {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--on-band);
}
.booker__day-date {
  font-weight: 600;
}
.booker__day-slots {
  font-size: 0.75rem;
  color: var(--muted);
}
.booker__day.is-chosen .booker__day-slots {
  color: var(--on-band-muted);
}

.booker__times {
  display: grid;
  gap: 0.75rem;
}
.booker__sub {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 400;
}
.booker__times .booker__times,
.booker__times > div {
  display: grid;
  gap: 0.5rem;
  grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
}
.booker__time {
  padding: 0.55rem 0.4rem;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 0.9375rem;
  cursor: pointer;
}
.booker__time:hover {
  border-color: var(--ink);
}
.booker__time.is-chosen {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--on-band);
}

.booker__detail {
  border-top: 1px solid var(--rule);
  padding-top: 1.25rem;
}
.booker__summary {
  margin: 0 0 1rem;
  font-size: 0.9375rem;
}
.booker__fields {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  margin-bottom: 1rem;
}
.booker__note {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--ink-soft);
}
.booker__note--error {
  color: #8a1c1c;
}
.booker__done {
  display: grid;
  gap: 0.6rem;
  padding: 1.25rem;
  border: 1px solid var(--ink);
}
.booker__done-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 400;
}
.booker__when {
  margin: 0;
  font-weight: 600;
}
.booker__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  margin: 0;
}
.booker__again {
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.booker__fallback {
  margin: 1.5rem 0 0;
  font-size: 0.9375rem;
  color: var(--ink-soft);
}

@media (max-width: 720px) {
  .booker__days { grid-template-columns: repeat(auto-fill, minmax(6.75rem, 1fr)); }
  .booker__times > div { grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr)); }
}

.booker__more {
  grid-column: 1 / -1;
  justify-self: start;
  margin-top: 0.35rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.9375rem;
  text-decoration: underline;
  cursor: pointer;
}

/* ---- Signing the model release (page: generic-model-release-form.html) ----
   The form itself reuses .form/.form__row/.form__field from the enquiry form; these are the few
   pieces the release adds. The wording lives in tools/forms-api/release-terms.txt. */
.form--release .form__row { grid-template-columns: 1fr; }
.form--release .form__field { max-width: 26rem; }
.form--release .btn { margin-top: 0.25rem; }

.kicker-h--small { font-size: 1rem; letter-spacing: 0.08em; margin-top: 2rem; }

.steps {
  margin: 0.5rem 0 0;
  padding-left: 1.15rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink);
}
.steps li { margin-bottom: 0.35rem; }

.release__meta {
  margin-top: 1.75rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(17, 17, 17, 0.12);
  font-size: 0.875rem;
  line-height: 1.6;
  color: rgba(17, 17, 17, 0.72);
}

/* ---------- Faces of Resilience: the exhibition ----------
   One woman per slide: her portrait, her story, her own words. The room is dark so the
   photographs carry it, and no portrait is ever cropped — the figure holds the height,
   the image keeps its own shape inside it. */

.ex-main { background: var(--band); color: var(--on-band); }

/* The band fills the window: heading at the top, slides in the middle, controls at the
   bottom, so a slide is never half-visible and the controls are never below the fold. */
.ex-main {
  min-height: calc(100svh - 6.6rem);
  display: flex;
  flex-direction: column;
}

.ex-head {
  flex: 0 0 auto;
  padding: clamp(1rem, 1.6vw, 1.5rem) 0 clamp(0.75rem, 1vw, 1rem);
  /* a hairline under the sticky header, as on the light pages */
  border-bottom: 1px solid var(--rule-band);
}
.ex-head__eyebrow {
  margin: 0 0 0.5rem;
  font-size: var(--step--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-band-muted);
}
.ex-head__title { font-family: var(--font-display); font-size: var(--step-2); }
.ex-head__lede {
  margin: 0.5rem 0 0;
  max-width: 52rem;
  color: var(--on-band-muted);
}

.ex { flex: 1 1 auto; display: flex; flex-direction: column; padding: 0; }

/* The track: one viewport of slides, snapping, swipeable, no scrollbar. */
.ex__viewport { flex: 1 1 auto; display: flex; min-height: 0; }
.ex__track {
  flex: 1 1 auto;
  display: flex;
  align-items: stretch;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
  overscroll-behavior-x: contain;
}
.ex__track::-webkit-scrollbar { display: none; }
.ex__track:focus-visible { outline: 2px solid var(--on-band); outline-offset: -4px; }

.ex__slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: grid;
  grid-template-columns: minmax(0, 28rem) minmax(0, 44rem);
  justify-content: center;
  align-items: center;
  gap: clamp(1.75rem, 4vw, 4rem);
  width: 100%;
  /* the stage is 84rem wide at most, whatever the window: 100% is the slide's own width,
     so the padding absorbs the difference and no second slide is ever visible */
  padding: clamp(1rem, 1.6vw, 1.5rem) max(calc((100% - 84rem) / 2), var(--pad)) clamp(0.85rem, 1.4vw, 1.25rem);
}

.ex__figure {
  margin: 0;
  display: flex;
  justify-content: center;
  height: min(44svh, 26rem);
}
.ex__figure img {
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}

.ex__panel { max-width: 44rem; }

/* The Faith stories are several paragraphs each, where a Faces of Resilience slide
   holds one. The panel scrolls inside the band instead of the band growing, so the
   portrait stays beside the words and neither slide is ever half-visible. */
.ex__panel--scroll {
  /* the same height as the portrait beside it (see .ex__figure), so the slide is no taller
     than a Faces of Resilience slide and the controls stay above the fold */
  max-height: min(44svh, 26rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 0.9rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(244, 242, 239, 0.35) transparent;
}
.ex__panel--scroll::-webkit-scrollbar { width: 6px; }
.ex__panel--scroll::-webkit-scrollbar-thumb { background: rgba(244, 242, 239, 0.3); }
.ex__panel--scroll .ex__story p + p { margin-top: 0.85rem; }
.ex__index {
  margin: 0 0 0.35rem;
  font-size: var(--step--1);
  letter-spacing: 0.18em;
  color: var(--on-band-muted);
}
.ex__name {
  font-family: var(--font-display);
  font-size: var(--step-2);
  margin-bottom: 0.85rem;
}
.ex__story {
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--on-band-muted);
}
.ex__quote { margin: 1.5rem 0 0; padding-left: 1.25rem; border-left: 2px solid rgba(244, 242, 239, 0.35); }
.ex__quote p {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.35;
}

/* Controls: previous / next, where you are, and everyone's name as a way in. */
.ex__bar { flex: 0 0 auto; padding: 0 0 clamp(0.85rem, 1.5vw, 1.25rem); }
.ex__bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.ex__count {
  margin: 0;
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  color: var(--on-band-muted);
}
.ex__btn {
  padding: 0.6rem 1.1rem;
  border: 1px solid rgba(244, 242, 239, 0.4);
  background: transparent;
  color: var(--on-band);
  font: inherit;
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}
.ex__btn:hover:not(:disabled) { background: var(--on-band); color: var(--band); }
.ex__btn:disabled { opacity: 0.35; cursor: default; }

.ex__names {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.25rem;
  margin: clamp(0.75rem, 1.4vw, 1.1rem) auto 0;
  padding: 0;
  list-style: none;
}
.ex__name-btn {
  padding: 0.25rem 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: none;
  color: var(--on-band-muted);
  font: inherit;
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}
.ex__name-btn:hover { color: var(--on-band); }
.ex__name-btn[aria-current='true'] { color: var(--on-band); border-bottom-color: var(--on-band); }

.ex-foot {
  padding: clamp(2rem, 4vw, 3.5rem) 0 clamp(3rem, 6vw, 5rem);
  border-top: 1px solid var(--rule-band);
  color: var(--on-band-muted);
  font-size: var(--step-0);
}
.ex-foot a { color: var(--on-band); }
.ex-foot__back { margin: 1.5rem 0 0; }
.ex-access__note { margin-top: 1rem; font-size: var(--step--1); color: var(--muted); }

/* ---------- The exhibition's password page (served by the API) ---------- */

.gate-body { background: var(--band); color: var(--on-band); }

.gate {
  max-width: 34rem;
  margin: 0 auto;
  padding: clamp(3rem, 10vh, 7rem) var(--pad);
}
.gate__eyebrow {
  margin: 0 0 0.75rem;
  font-size: var(--step--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-band-muted);
}
.gate__title { font-family: var(--font-display); font-size: var(--step-3); margin-bottom: 1rem; }
.gate__lede { color: var(--on-band-muted); font-size: var(--step-0); }

.gate__form { margin: 2rem 0 0; }
.gate__label {
  display: block;
  margin-bottom: 0.4rem;
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--on-band-muted);
}
.gate__input {
  width: 100%;
  padding: 0.75rem 0.85rem;
  border: 1px solid rgba(244, 242, 239, 0.35);
  background: rgba(244, 242, 239, 0.06);
  color: var(--on-band);
  font: inherit;
}
.gate__input:focus-visible { outline: 2px solid var(--on-band); outline-offset: 2px; }
.gate__form .btn { margin-top: 1rem; }
.gate__form .btn--solid { background: var(--on-band); border-color: var(--on-band); color: var(--band); }

.gate__error {
  margin: 1.25rem 0 0;
  padding: 0.75rem 1rem;
  border-left: 3px solid #d98080;
  background: rgba(217, 128, 128, 0.12);
  font-size: var(--step--1);
}
.gate__help,
.gate__back { margin-top: 1.75rem; font-size: var(--step--1); color: var(--on-band-muted); }
.gate__help a,
.gate__back a { color: var(--on-band); }

.btn--on-dark { border-color: rgba(244, 242, 239, 0.4); color: var(--on-band); }

/* ---------- Project pages: Faces of Resilience, Faith, and every project after ----------
   A project page is one shape, the same for every project: a title and the project's own line,
   what it is about, the way into the exhibition, where it has been shown, who is behind it, how
   to support it, and a closing band of photographs. `class="page-project"` on the body turns it
   on, so the other pages of the site are untouched.

   Two rules make it a format rather than a layout:

   1. One heading, one size. Before this, section headings were 13px uppercase sans while the
      page title and the newsletter heading were 48px serif — the same job wearing three faces.
      Now every heading is the display serif at --step-2, and the only larger line is the title.
   2. One body size, one rhythm. Body copy is --step-0 everywhere (the support paragraph and the
      newsletter line used to be 22px while everything else was 17px); the one larger line is the
      introduction under the title, where a visitor starts reading. Sections carry --section-y of
      their own — about 52px at 1707px instead of 112px, which was 224px of gap between
      sections. */

.page-project {
  --section-y: clamp(2rem, 3.4vw, 3.25rem);
  --project-gap: clamp(1.25rem, 2vw, 1.75rem);
}

.page-project .section { padding: var(--section-y) 0; }

/* Scoped to <main>: the footer sits outside it and has its own headings (.footer__h), which
   these page-level rules used to restyle into 34px dark text — invisible on the dark footer, so
   the project pages' footers lost their column headings and grew 40px taller than every other
   page's. Anything below that styles a bare element on a project page belongs inside main. */
.page-project main .kicker-h,
.page-project main h2:not(.testimonial__name) {
  font-family: var(--font-display);
  font-size: var(--step-2);
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
  margin-bottom: 0.6rem;
}

.page-project main .display,
.page-project main .page-head h1 {
  font-size: clamp(1.75rem, 1.3rem + 1.9vw, 2.75rem);
  max-width: 34ch;
  margin: 0 auto;
}

.page-project main p,
.page-project main .lede { font-size: var(--step-0); }
/* The narrative column: at 17px the full 1184px wrap is about 140 characters a line, which is
   hard work to read. Project copy gets a measure instead of the whole page width. */
.page-project .section > .wrap > p { max-width: 40rem; }
.page-project .page-head .lede { font-size: var(--step-1); margin-top: 1rem; }
.page-project .section p + p { margin-top: var(--project-gap); }
/* Everything on a project page is centred, as the title already was: the page reads as one
   column down the middle rather than a title in the centre and the rest of the page ranged left.
   The one thing centring breaks is a bulleted list — a dot parked at the left of a centred line
   floats free of its own text — so project lists drop the marker and their lines sit centred. */
.page-project .section .wrap { text-align: center; }
.page-project .section > .wrap > p,
.page-project .checklist,
.page-project .detail-list { margin-left: auto; margin-right: auto; }

.page-project .checklist {
  gap: 0.55rem;
  justify-items: center;
  max-width: 44rem;
  margin: 1.25rem auto 0;   /* its own 2rem bottom margin added 32px to the section gap */
}
.page-project .checklist li { padding-left: 0; }
.page-project .checklist li::before { display: none; }

.page-project .logos { gap: clamp(1.5rem, 3vw, 2.5rem); justify-content: center; }
.page-project .quote { padding: var(--section-y) 0; }
.page-project .quote__text { font-size: var(--step-2); }
.page-project .newsletter .display { max-width: none; }

.btn--on-dark:hover { background: var(--on-band); border-color: var(--on-band); color: var(--band); }

@media (max-width: 900px) {
  .ex__slide {
    grid-template-columns: 1fr;
    min-height: 0;
    gap: clamp(1.25rem, 4vw, 2rem);
    text-align: left;
  }
  .ex__figure { height: min(48svh, 26rem); }
  .ex__panel--scroll { max-height: min(48svh, 26rem); }
  .ex__panel { max-width: none; }
}

@media (max-width: 720px) {
  .ex__names { gap: 0.3rem 0.9rem; }
  .ex__bar-inner { gap: 0.5rem; }
}


/* ---------- The testimonials page (the ones Steph approves) ----------
   One card per testimonial, photograph above words, centred: the same centred shape as the project
   pages, so the page reads as part of the site rather than a list. `.form--wide` is the page's form
   column — narrower than the page, centred, and left-aligned inside, because a form is not prose. */
.form--wide { max-width: 40rem; margin-inline: auto; }

.tst-wrap { margin-top: 2.5rem; }
.tst {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.75rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  align-items: start;
}
.tst__group { margin-top: 3.5rem; }
.tst__group:first-child { margin-top: 0; }
.tst__group > .kicker-h { margin-bottom: 1.5rem; }
.tst__item {
  display: grid;
  gap: 0.7rem;
  justify-items: center;
  align-content: start;
  text-align: center;
  padding: 1.75rem 1.5rem;
  background: var(--paper);
  border: 1px solid var(--rule);
}
.tst__photo {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
}
.tst__words { margin: 0; font-size: 1rem; line-height: 1.6; }
.tst__name { margin: 0; font-weight: 600; }
.tst__role { margin: 0; color: var(--muted); font-size: 0.875rem; }
.tst__empty { color: var(--muted); }

@media (max-width: 40rem) {
  .tst { grid-template-columns: 1fr; }
}
