/* ------------------------------------------------------------------
   Adam Browning-Hill — Photography Portfolio
   Upscale, elegant, editorial styling
-------------------------------------------------------------------*/

:root {
  --ink: #14130f;
  --paper: #faf8f5;
  --grey: #8c887f;
  --line: #e4e0d8;
  --serif: 'Fraunces', Georgia, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  /* One gutter width for the whole site. The hand-ordered .photo-row blocks
     were always 5px while the masonry .grid used 8px, so the two sections of
     the home page didn't match. 5px is the narrower of the two and the one
     used on the most pages, so everything now follows it. */
  --gap: 5px;
  /* Maximum width of the page content. Raised from 1400px (23 Aug):
     on large or zoomed-out screens the site sat as a narrow column
     with wide empty margins either side. Photos are stored up to
     1900px, so going much beyond this would start upscaling them. */
  --page: 1800px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; text-decoration: none; }

h1, h2 {
  font-family: 'Jost', var(--sans);
  font-weight: 400;
  letter-spacing: normal;
  margin: 0;
}

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

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(250, 248, 245, 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.header-inner {
  max-width: var(--page);
  margin: 0 auto;
  padding: 22px 40px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.logo {
  font-family: 'Jost', var(--sans);
  font-size: 15px;
  letter-spacing: normal;
  font-weight: 300;
  color: var(--grey);
}

.logo--hidden {
  visibility: hidden;
}

.nav-wrap {
  position: relative;
}

.nav-toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--gap);
  background: none;
  border: none;
  cursor: pointer;
  padding: 10px 6px;
}

.nav-toggle span {
  width: 24px;
  height: 1px;
  background: var(--ink);
  display: block;
  transition: opacity 0.2s ease;
}

.nav-wrap:hover .nav-toggle span,
.nav-wrap.open .nav-toggle span {
  opacity: 0.6;
}

.nav-panel {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 6px;
  background: rgba(10, 9, 7, 0.74);
  backdrop-filter: blur(6px);
  padding: 10px 0;
  min-width: 160px;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
  box-shadow: 0 18px 40px rgba(20, 19, 15, 0.22);
  z-index: 1;
}

/* invisible bridge so the pointer never loses hover moving from the
   hamburger button down into the panel */
.nav-panel::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -10px;
  height: 10px;
}

.nav-wrap:hover .nav-panel,
.nav-wrap.open .nav-panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.nav-panel a {
  padding: 11px 18px;
  color: #fff;
  opacity: 0.9;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: opacity 0.2s ease, background 0.2s ease;
}

.nav-panel a:hover,
.nav-panel a.active {
  opacity: 1;
  background: rgba(255, 255, 255, 0.08);
}

/* ---------------- Hero ---------------- */

.hero {
  position: relative;
  height: 92vh;
  min-height: 520px;
  overflow: hidden;
}

.hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 25%;
}

.site-header--home .header-inner {
  padding-top: 16px;
  padding-bottom: 8px;
}

.hero-name-block {
  text-align: center;
  padding: 6px 24px 30px;
}

.hero-name-block h1 {
  font-family: 'Jost', var(--sans);
  font-size: clamp(34px, 5.2vw, 58px);
  font-weight: 200;
  text-transform: uppercase;
  color: var(--ink);
  margin-bottom: 8px;
}

.hero-name-block h1 .name-track { letter-spacing: 0.30em; }
.hero-name-block h1 .name-tight { margin-right: 0.12em; }
.hero-name-block h1 .name-space { letter-spacing: 0.16em; }
.hero-name-block h1 .name-hyphen { letter-spacing: 0.14em; }

.hero-name-block p {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--grey);
}

/* ---------------- Intro ---------------- */

.intro {
  max-width: 640px;
  margin: 80px auto 40px;
  padding: 0 40px;
  text-align: center;
}

.intro p {
  font-family: var(--sans);
  font-weight: 300;
  font-size: 20px;
  line-height: 1.5;
  color: var(--ink);
  opacity: 0.85;
}

/* ---------------- Grids (JS-packed masonry) ----------------
   Photos are distributed into .grid-col wrapper divs by script.js, which
   always appends the next photo to whichever column is currently shortest.
   This avoids the trailing empty-space gaps that CSS column-count masonry
   produces when the last column happens to run short. Until that JS runs,
   .grid falls back to a simple flex row so nothing is invisible. */

.grid {
  max-width: var(--page);
  margin: 0 auto;
  padding: 20px 40px 100px;
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
  opacity: 0;
}

.grid.masonry-ready {
  opacity: 1;
  transition: opacity 0.3s ease;
}

.grid-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* Home page only. The grid's own 20px top padding is dropped to one gutter
   here, so its columns start the same distance below the hand-placed lead
   rows above as photos sit apart from each other everywhere else.

   No per-column offset is needed: the last lead row is trimmed to finish
   level (see home-suit-trimmed.jpg in build.py), so all four columns start
   from the same line. A negative margin was tried instead, but the overhang
   it corrected scales with column width, so any fixed pixel value drifts
   out as the window resizes. */
@media (min-width: 901px) {
  .mixed-grid {
    padding-top: var(--gap);
  }

  /* The lead section's left stack runs longer than its right (the Emirates
     ad was added to the left only), so the grid below would otherwise start
     beneath the longer side, leaving a white band under the right stack.
     Columns 3 and 4 are pulled up by that difference to fill it.

     The value is a PERCENTAGE deliberately, not pixels: a margin percentage
     resolves against the container's WIDTH, and every stack height here is
     an image scaled to its column width — so the difference stays the same
     fraction of the width at any window size. A fixed px value would only
     be correct at one width. Recalculate if either stack's photos change. */
  .mixed-grid .grid-col:nth-child(3),
  .mixed-grid .grid-col:nth-child(4) {
    margin-top: -35.672%;
  }

  /* A photo widened to run across its own column plus the one to its right.
     The grid is four independent flex columns, so a tile can't span them the
     way a real CSS grid would; instead it's drawn at double width and simply
     overflows into its neighbour. That only works because the slot it covers
     is a .grid-blank (below) and nothing follows it in that column, so
     there's nothing for it to collide with. */
  .mixed-grid .photo.span-2 {
    width: calc(200% + var(--gap));
    z-index: 1;
  }
}

/* The lower half of the home page's lead section: two half-width stacks that
   fill independently, so a photo added to one side pushes only that side down
   instead of dragging its opposite number with it. (The rows above stay a
   shared 4-column grid, because there the tiles are meant to line up.) */
.lead-split {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
  margin-bottom: var(--gap);
}

.lead-col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* Two photos side by side within a stack, at half its width each. */
.lead-pair {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap);
  align-items: start;
}

@media (max-width: 900px) {
  .lead-split { flex-direction: column; }
}

/* An empty slot kept in the running order purely to hold a column position —
   see render_mix_item's "blank" case in build.py. It must stay in the list
   (removing it would shift every later photo into a different column) but
   must not take up any height. */
.grid-blank {
  height: 0;
  margin-top: calc(-1 * var(--gap));
}

.photo {
  margin: 0;
  position: relative;
  overflow: hidden;
  cursor: pointer;
}

.photo img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

.photo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgba(10, 9, 7, 0.5);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}

.photo:hover::after { opacity: 1; }

.photo:hover img { transform: scale(1.045); }

.photo figcaption {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 24px;
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}

.photo:hover figcaption {
  opacity: 1;
}

.photo figcaption span {
  color: #fff;
  font-size: 16px;
  font-weight: 300;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  line-height: 1.8;
  white-space: pre-line;
}

@media (max-width: 900px) {
  .grid { gap: var(--gap); }
}

/* ---------------- Beauty/fashion hand-ordered rows ----------------
   Each row is its OWN independent 3-column CSS grid, containing only the
   shoots Adam grouped together in his layout deck (see BEAUTY_ROW_LENGTHS
   / FASHION_ROW_LENGTHS in build.py). A shared masonry grid — dense or
   sparse auto-flow — lets one row's image heights push items into the
   wrong row, or swap two shoots' left-right order, once photos have
   different natural heights. Isolating each row removes that failure mode
   entirely: items can only render in the row and position Adam placed
   them in, full stop. Shoots flagged data-wide span 2 of the 3 columns in
   their row, data-full span all 3; a row with fewer shoots than 3 columns
   worth simply ends there rather than stretching to fill the width,
   matching the gap Adam's own layout has in that spot. */
.beauty-rows {
  max-width: var(--page);
  margin: 0 auto;
  padding: 20px 40px 100px;
}

.photo-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: start;
  gap: var(--gap);
  margin-bottom: var(--gap);
}

.photo-row .photo[data-wide="true"] {
  grid-column: span 2;
}

/* A row whose columns have been sized to its photos' shapes (build.py emits
   an inline grid-template-columns so everything in the row scales to one
   common height). The wide/full span flags counted fixed columns, so they'd
   fight that — each photo simply takes its own column here. */
.photo-row[style*="grid-template-columns"] .photo[data-wide="true"],
.photo-row[style*="grid-template-columns"] .photo[data-full="true"] {
  grid-column: auto;
}

.photo-row .photo[data-full="true"] {
  grid-column: span 3;
}

/* 19 Aug: commercial page only — 4 columns instead of 3, so images sit
   smaller and more rows show on screen at once. data-wide still spans 2
   (now half the row instead of two-thirds); data-full needs its own
   override to span all 4. */
.photo-row.four-col {
  grid-template-columns: repeat(4, 1fr);
}

.photo-row.four-col .photo[data-full="true"] {
  grid-column: span 4;
}

/* 20 Aug — internal marker only (commercial page): flags an empty grid
   slot reserved for a photo Kirstie hasn't supplied yet, so it's obvious
   at a glance rather than reading as an unexplained gap. Aspect-ratio
   matches difc (2.03:1) so it sits at the same height as the row's other
   image and doesn't itself introduce a new gap. Remove once a photo (or
   two) fills the slot. */
.photo-placeholder {
  aspect-ratio: 2.03 / 1;
  border: 2px dashed #c0392b;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #c0392b;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  box-sizing: border-box;
}

@media (max-width: 900px) {
  .photo-row { grid-template-columns: repeat(2, 1fr); }
  .photo-row .photo[data-wide="true"],
  .photo-row .photo[data-full="true"] {
    grid-column: span 2;
  }
}

/* For a run of plain 3-up rows, the 1st+2nd shoot of each row stay
   row-locked (.beauty-pair, stacked inside .beauty-main) exactly as
   Adam grouped them, while the 3rd shoot of each of those rows is
   pulled into .beauty-rail — an independent flex column running
   alongside the whole run — so it can sit directly under the previous
   rail shoot instead of being forced to match its old row-mates'
   height. .beauty-main:.beauty-rail is a 2:1 split, matching the 2-of-3
   vs 1-of-3 column widths those shoots had in the original 3-col grid,
   so nothing changes size — it just closes the vertical gaps. */
.beauty-split {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
  margin-bottom: var(--gap);
}

/* Same split mechanism, mirrored — rail column on the left, main pairs
   on the right, for rows where Adam staggered the single column first. */
.beauty-split.reverse {
  flex-direction: row-reverse;
}

/* Bottom-aligns the rail and main columns of a split block instead of the
   default top-align — used where the taller column (e.g. ayan-hat) should
   hang level with the shorter column's bottom edge, extending upward past
   its top rather than downward past its bottom. */
.beauty-split.align-bottom {
  align-items: flex-end;
}

.beauty-main {
  flex: 2 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

.beauty-rail {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* 19 Aug — equal-width variant for the commercial page's 4-column grid,
   where a "wide" shoot spans 2 of 4 columns (50%) rather than 2 of 3
   (66%). Overrides the 2:1 beauty ratio to 1:1 so both flex columns stay
   the same width as the "wide" grid cells they replace. */
.beauty-split.even .beauty-main,
.beauty-split.even .beauty-rail {
  flex: 1 1 0;
}

.beauty-pair {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-items: start;
  gap: var(--gap);
}

/* 19 Aug — commercial page only: a 3-lane version of the split/rail
   mechanism above, for a block where a wide 2-column centre lane sits
   between two independently-flowing 1-column side lanes (Adam's
   suggested arrangement for the hair/sony/flydubai-georgia section).
   Each lane's flex-grow is set inline per its column weight (1, 2, or 1
   out of the row's 4), so it lines up with the plain 4-col grid rows
   immediately above and below it. */
.commercial-flow {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
  margin-bottom: var(--gap);
}

.commercial-flow-lane {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

@media (max-width: 900px) {
  .commercial-flow { flex-direction: column; }
  .commercial-flow-lane { flex: 1 1 auto !important; width: 100%; }
}

/* 20 Aug — true masonry (commercial page only): unlike .commercial-flow
   above (independent flex columns, sealed off from each other), every
   photo here gets an explicit grid-row span computed at build time from
   its real pixel height, so a photo can span multiple lanes and land
   exactly where a gap actually is. grid-auto-rows is a fine 1px unit with
   no row-gap — the 5px visual gap is baked into each item's own row-span
   instead, since row-gap would otherwise apply at every 1px row.
   Column-gap stays a normal CSS gap since there are only 4 fixed columns.
   Photos are cropped (object-fit: cover) rather than shown in full, since
   a fixed-px row-span can't reflow at other widths the way the rest of
   the page's fluid height:auto rows do. */
.commercial-masonry {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: var(--gap);
  row-gap: 0;
  grid-auto-rows: 1px;
  margin-bottom: var(--gap);
}

.commercial-masonry .photo img {
  /* Each grid cell's row-span already has 5px baked in for the vertical
     gap (row-gap is 0 — build.py adds it to the computed span instead),
     so the image itself has to stop 5px short of the cell's full height,
     otherwise it stretches into that space and the white line between
     stacked photos disappears. */
  height: calc(100% - 5px);
  object-fit: cover;
}

@media (max-width: 900px) {
  /* Fixed row-spans were computed for the 1400px desktop design width —
     meaningless at mobile widths, so drop back to a plain 2-col flow with
     natural (uncropped) heights instead of trying to reflow the grid. */
  .commercial-masonry {
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: auto;
    gap: var(--gap);
  }
  .commercial-masonry .photo {
    grid-column: auto !important;
    grid-row: auto !important;
  }
  .commercial-masonry .photo img {
    height: auto;
    object-fit: initial;
  }
}

@media (max-width: 900px) {
  .beauty-split, .beauty-split.reverse { flex-direction: column; }
  .beauty-main, .beauty-rail { flex: 1 1 auto; width: 100%; }
  .beauty-main { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gap); }
  .beauty-pair { display: contents; }
  .beauty-rail { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gap); }
}

/* ---------------- Cars grid (hand art-directed rows) ----------------
   Unlike the auto-balancing masonry above, the cars page follows Kirstie's
   exact row-by-row layout: the number of photos per row varies, and the
   closing row has one wide photo beside two narrower stacked photos. No JS
   involved — this is plain CSS flex, so it renders in the requested order
   every time. */

.cars-grid {
  max-width: var(--page);
  margin: 0 auto;
  padding: 20px 40px 100px;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

.cars-row {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
}

.cars-row > .photo {
  flex: 1 1 0;
  min-width: 0;
}

/* Reserved slot for a photo Kirstie hasn't chosen yet — holds the row's
   shape at a plausible 4:3 aspect so the layout doesn't collapse. */
.photo--placeholder {
  aspect-ratio: 4 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed rgba(0, 0, 0, 0.2);
  background: rgba(0, 0, 0, 0.03);
  color: rgba(0, 0, 0, 0.35);
  font-family: "Inter", sans-serif;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* The split row stretches both children (the wide photo and the stacked
   pair) to match heights — without this, the stacked pair has no way to
   know how tall to be, since neither its own natural content nor its
   flex-basis:0 children give it an intrinsic height. Photos inside then
   use object-fit: cover to fill whatever height they're stretched to. */
.cars-row--split {
  align-items: stretch;
}

.cars-row--split > .photo:first-child {
  flex: 1.4 1 0;
}

.cars-substack {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* Once .cars-substack is stretched to the row's height by the parent's
   align-items: stretch, these two panes split that definite height evenly
   — and crop their photos to fill it, since two very differently-shaped
   photos can't both keep their natural aspect ratio and still fill an
   exact half-height slot. */
.cars-substack > .photo {
  flex: 1 1 0;
  min-height: 0;
  height: 100%;
}

.cars-substack > .photo img {
  height: 100%;
  object-fit: cover;
}

/* Mirror of .cars-row--split: a wide standalone photo (e.g. the desert
   dunes shot) alongside a matching-height pair of photos, but this time the
   pair sits side by side rather than stacked. Same stretch/cover trick so
   both companions fill the row's full height evenly. */
.cars-row--splith {
  align-items: stretch;
}

.cars-subrow {
  min-width: 0;
  display: flex;
  flex-direction: row;
  gap: var(--gap);
}

.cars-subrow > .photo {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
}

.cars-subrow > .photo img {
  height: 100%;
  object-fit: cover;
}

@media (max-width: 900px) {
  .cars-grid { padding-left: 24px; padding-right: 24px; }
  .cars-row,
  .cars-row--split,
  .cars-row--splith,
  .cars-substack,
  .cars-subrow {
    flex-direction: column;
  }
}

/* ---------------- CTA ---------------- */

.cta {
  text-align: center;
  padding: 0 40px 120px;
}

.btn {
  display: inline-block;
  padding: 16px 42px;
  border: 1px solid var(--ink);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  transition: background 0.25s ease, color 0.25s ease;
}

.btn:hover {
  background: var(--ink);
  color: var(--paper);
}

/* ---------------- Collection / page headers ---------------- */

.collection-header,
.page-header {
  max-width: var(--page);
  margin: 0 auto;
  padding: 72px 40px 12px;
}

.collection-header h1,
.page-header h1 {
  font-family: 'Jost', var(--sans);
  font-weight: 400;
  font-size: clamp(28px, 4vw, 42px);
  letter-spacing: normal;
  text-transform: lowercase;
  color: #34322b;
}

.collection-header p {
  margin-top: 14px;
  color: var(--grey);
  font-size: 15px;
  max-width: 480px;
}

/* ---------------- About ---------------- */

.about-content {
  max-width: 1100px;
  margin: 40px auto 120px;
  padding: 0 40px;
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: 60px;
  align-items: center;
}

.about-image img { width: 100%; }

.about-text p {
  font-size: 17px;
  line-height: 1.75;
  color: #34322b;
  margin-bottom: 20px;
}

@media (max-width: 800px) {
  .about-content { grid-template-columns: 1fr; }
}

/* ---------------- Contact ---------------- */

/* Contained BTS shot, same width treatment as .about-content (max-width
   1100px, 0 40px padding) so it sits in the page the same way the About
   imagery does. The enquiry form panel is absolutely positioned inside the
   bright softbox area at the top-left of the shot — landscape in shape and
   short enough to stay clear of the people below it, so nobody in the
   photo is covered. */
.contact-photo {
  position: relative;
  max-width: 1100px;
  margin: 40px auto 0;
  padding: 0 40px;
}

.contact-photo img {
  width: 100%;
  display: block;
}

.contact-photo-caption {
  margin: 18px 0 120px;
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--grey);
}

.contact-form-panel {
  position: absolute;
  top: 32px;
  left: 40px;
  width: min(600px, 66%);
  background: rgba(250, 248, 245, 0.97);
  padding: 32px 40px;
  box-shadow: 0 20px 50px rgba(20, 19, 15, 0.14);
}

@media (max-width: 800px) {
  .contact-form-panel {
    position: static;
    width: auto;
    margin: -1px 0 0;
    box-shadow: none;
    padding: 32px 24px;
  }

  .contact-photo-caption {
    margin-bottom: 80px;
  }
}

.contact-lead {
  font-family: var(--sans);
  font-weight: 300;
  font-size: 15px;
  margin: 0 0 18px;
  text-align: left;
}

.contact-form {
  text-align: left;
  margin-top: 8px;
}

.contact-form--compact .form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

.contact-form--compact .form-row {
  margin-bottom: 16px;
}

.contact-form--compact .form-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-top: 2px;
}

.contact-form--compact .btn {
  width: auto;
  flex: 0 0 auto;
  padding: 13px 30px;
  margin-top: 0;
}

.contact-social-inline {
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.75;
}

@media (max-width: 500px) {
  .contact-form--compact .form-grid {
    grid-template-columns: 1fr;
  }

  .contact-form--compact .form-actions {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
  }
}

.form-row {
  margin-bottom: 22px;
}

.form-row label {
  display: block;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 8px;
}

.form-row input,
.form-row textarea {
  width: 100%;
  border: none;
  border-bottom: 1px solid var(--line);
  background: transparent;
  font-family: var(--sans);
  font-size: 16px;
  color: var(--ink);
  padding: 8px 2px;
  resize: vertical;
  transition: border-color 0.25s ease;
}

.form-row input:focus,
.form-row textarea:focus {
  outline: none;
  border-color: var(--ink);
}

.contact-form .btn {
  width: 100%;
  background: none;
  cursor: pointer;
  margin-top: 8px;
}

.contact-form .btn:disabled {
  opacity: 0.5;
  cursor: default;
}

.form-status {
  margin-top: 16px;
  font-size: 13px;
  min-height: 18px;
}

.form-status.success { color: #3a6b4a; }
.form-status.error { color: #a53f3f; }

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

.site-footer {
  border-top: 1px solid var(--line);
  padding: 46px 40px;
}

.footer-inner {
  max-width: var(--page);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.footer-logo {
  font-family: 'Jost', var(--sans);
  font-weight: 300;
  letter-spacing: normal;
  font-size: 14px;
  color: var(--grey);
}

.footer-links {
  display: flex;
  gap: 26px;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
}

.footer-meta {
  font-size: 11px;
  color: var(--grey);
}

/* ---------------- Lightbox ---------------- */

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(10, 9, 7, 0.9);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  /* No side padding: it used to reserve room for the arrows, but it also
     capped how wide a photo could be, which stopped the widest shots from
     ever reaching the full height of the window. The arrows sit over the
     photo's edges instead. */
  padding: 0;
}

.lightbox.open { display: flex; }

.lightbox-frame {
  position: relative;
  max-width: 100vw;
  max-height: 100vh;
  line-height: 0;
  /* This is a flex item, and a flex item won't shrink below its content's
     natural size unless min-width is cleared. Without this, a photo scaled
     to the full window height forces the frame wider than the window and
     the picture spills off both edges instead of fitting. */
  min-width: 0;
}

/* Fill the full height of the window, whatever the photo's shape, so a
   landscape shot doesn't sit letterboxed with dark bands above and below it.
   Width simply follows from the height. max-width is the one guard: on an
   unusually narrow or tall window a wide photo would otherwise run off the
   sides, so there it falls back to fitting the width instead — better than
   cropping the picture. */
.lightbox img {
  height: 100vh;
  width: auto;
  max-width: 100%;
  display: block;
  object-fit: contain;
}

.lightbox-caption {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 24px;
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
  background: rgba(10, 9, 7, 0.5);
}

.lightbox-frame:hover .lightbox-caption {
  opacity: 1;
}

.lightbox-caption span {
  color: #fff;
  font-size: 16px;
  font-weight: 300;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  line-height: 1.8;
  white-space: pre-line;
}

.lightbox-close {
  position: absolute;
  top: 28px;
  right: 36px;
  color: #fff;
  font-size: 28px;
  background: none;
  border: none;
  cursor: pointer;
  opacity: 0.8;
}

.lightbox-close:hover { opacity: 1; }

.lightbox-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  color: #fff;
  font-size: 44px;
  line-height: 1;
  background: none;
  border: none;
  cursor: pointer;
  opacity: 0.7;
  padding: 12px 18px;
  transition: opacity 0.2s ease;
}

.lightbox-arrow:hover { opacity: 1; }

.lightbox-prev { left: 8px; }
.lightbox-next { right: 8px; }

.lightbox-gallery-btn {
  position: absolute;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  display: none;
  align-items: center;
  gap: 9px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #fff;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 11px 20px;
  border-radius: 999px;
  cursor: pointer;
  opacity: 0.9;
  transition: background 0.2s ease, opacity 0.2s ease;
}

.lightbox-gallery-btn.visible { display: flex; }
.lightbox-gallery-btn:hover { background: rgba(255, 255, 255, 0.2); opacity: 1; }
.lightbox-gallery-btn svg { width: 15px; height: 15px; flex-shrink: 0; }

@media (max-width: 600px) {
  .lightbox-arrow { font-size: 32px; padding: 8px 10px; }
  .lightbox-prev { left: 0; }
  .lightbox-next { right: 0; }
  .lightbox-gallery-btn { bottom: 18px; font-size: 10px; padding: 9px 16px; }
  .lightbox-gallery-btn span { display: none; }
}

/* ---------------- Mobile nav ---------------- */

@media (max-width: 860px) {
  .nav-panel {
    left: -6px;
    min-width: 160px;
  }

  .header-inner { padding: 18px 24px; }
  .hero-caption { left: 24px; }
  .grid { padding-left: 24px; padding-right: 24px; }
  .collection-header, .page-header, .about-content { padding-left: 24px; padding-right: 24px; }
}

@media (max-width: 600px) {
  .hero-name-block {
    padding-left: 16px;
    padding-right: 16px;
  }

  .hero-name-block h1 {
    font-size: 6.2vw;
    white-space: nowrap;
  }

  .hero-name-block h1 .name-track { letter-spacing: 0.08em; }
  .hero-name-block h1 .name-space { letter-spacing: 0.05em; }
  .hero-name-block h1 .name-hyphen { letter-spacing: 0.05em; }
  .hero-name-block h1 .name-tight { margin-right: 0.02em; }
}

/* ---------------- Contact — split screen ----------------
   Chosen 23 Aug from four mockups. Photo fills one half floor to ceiling,
   form on the other, so the form is the obvious purpose of the page rather
   than an afterthought beneath the picture. Name and email are stacked so
   each field runs the panel's full width. */
.contact-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: calc(100vh - 92px);
}

.contact-split-pic {
  position: relative;
  overflow: hidden;
  background: #0b0f14;
}

.contact-split-pic img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.contact-split-cap {
  position: absolute;
  left: 24px;
  bottom: 20px;
  color: #fff;
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.85;
}

.contact-split-panel {
  display: flex;
  align-items: center;
  padding: 70px 8vw;
}

.contact-split-inner {
  width: 100%;
  max-width: 460px;
}

.contact-split-inner h1 {
  font-size: clamp(28px, 4vw, 42px);
  color: #34322b;
  margin-bottom: 14px;
}

.contact-split-inner .contact-lead {
  font-size: 16px;
  line-height: 1.6;
  color: #4a463f;
  margin: 0 0 32px;
}

.contact-split-inner .form-row + .form-row {
  margin-top: 18px;
}

.contact-split-inner .form-actions {
  margin-top: 26px;
}

.contact-split-meta {
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
  font-size: 14px;
  color: var(--grey);
  line-height: 2;
}

@media (max-width: 900px) {
  .contact-split { grid-template-columns: 1fr; min-height: 0; }
  .contact-split-pic { height: 52vh; }
  .contact-split-panel { padding: 50px 24px 70px; }
}

/* ---------------- About — magazine covers ----------------
   A single row of covers. Each figure's flex-grow is set from its own
   aspect ratio (see ABOUT_COVERS in build.py), so covers of slightly
   different trim sizes all render at one common height instead of
   stepping up and down. On narrow screens the row scrolls sideways
   rather than shrinking the covers to stamps. */
.covers {
  max-width: var(--page);
  margin: 0 auto;
  padding: 10px 40px 100px;
}

.covers h2 {
  font-family: 'Jost', var(--sans);
  font-weight: 400;
  font-size: clamp(20px, 2.4vw, 28px);
  text-transform: lowercase;
  color: #34322b;
  margin-bottom: 22px;
}

.covers-row {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
}

/* The Esquire cover is a full page layout whose white margin is part of the
   design — masthead and cover lines sit on it. Against the site's off-white
   background it would otherwise dissolve at the edges, so it gets a hairline
   to hold its shape. The other covers are photographs bleeding to the trim
   and need no outline. */
.covers-row .cover--outlined img {
  outline: 1px solid rgba(20, 19, 15, 0.22);
  outline-offset: -1px;
}

.covers-row .cover {
  margin: 0;
  min-width: 0;
}

.covers-row .cover img {
  width: 100%;
  height: auto;
  display: block;
}

.covers-row .cover figcaption {
  margin-top: 8px;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
  line-height: 1.5;
}

@media (max-width: 900px) {
  .covers { padding: 10px 22px 70px; }
  .covers-row {
    overflow-x: auto;
    padding-bottom: 8px;
    -webkit-overflow-scrolling: touch;
  }
  .covers-row .cover { flex: 0 0 46% !important; }
}

/* Photographer credit under Adam's own portrait on the About page. Set in
   the same small, letter-spaced caps as the cover captions so it reads as a
   credit rather than body copy. */
.about-image {
  margin: 0;
}

.about-image figcaption {
  margin-top: 8px;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
}
