/* Gallery styling.
 *
 * Visual language borrowed from JoaoFranco03/photography-portfolio (MIT): light
 * ground, no accent colour, Signika for everything, a lot of air around a
 * large-tracked uppercase title, and a hairline underline that grows on hover.
 * The photographs are the only colour on the page.
 *
 * Layout is the flex-grow-proportional-to-aspect-ratio approach used by 500px and
 * Flickr: because flex-grow and flex-basis are both set to the ratio, flexbox
 * scales every frame in a row by the same factor, so ratios survive and rows fill
 * the width exactly. Upstream instead gave each tile a fixed viewport-derived box
 * and `background-size: cover`, which is why portrait frames were being cropped
 * to landscape.
 *
 * Loaded after main.min.css and deliberately overrides most of it.
 */

@import url("https://fonts.googleapis.com/css2?family=Signika:wght@300;400;600;700&display=swap");

:root {
  --gap: 10px;
  --row-h: 320px;
  --ground: #ffffff;
  --ink: #111111;
  --ink-soft: #555555;
  --ink-faint: #8a8a8a;
  --rule: rgba(17, 17, 17, 0.14);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --ground: #000000;
    --ink: #f5f5f5;
    --ink-soft: #b0b0b0;
    --ink-faint: #6f6f6f;
    --rule: rgba(245, 245, 245, 0.16);
  }
}

/* ---- ground ------------------------------------------------------------ */

html,
body {
  background: var(--ground) !important;
  color: var(--ink);
  font-family: "Signika", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-weight: 400;
}

body.is-preload,
body.loading {
  opacity: 1 !important;
}

/* Upstream ships `strong, b { color: #fff }` for its dark theme. On a light
   ground that is white-on-white — it made the page title invisible, and would do
   the same to any bold text. */
strong,
b {
  color: inherit;
  font-weight: 600;
}

#wrapper {
  background: var(--ground);
  margin: 0 auto;
  max-width: 1680px;
  padding: 0 1.25rem;
}

@media (min-width: 768px) {
  #wrapper { padding: 0 5rem; }
}

/* ---- masthead ---------------------------------------------------------- */

#header {
  align-items: baseline;
  background: none !important;
  border: 0 !important;
  box-shadow: none !important;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  height: auto !important;
  justify-content: space-between;
  padding: 3.5rem 0 0 !important;
  position: static !important;
  width: auto !important;
}

/* Upstream sets `#header h1 { font-size: 1em; color: #a0a0a1 }`, which flattened
   the title into the byline. Restated here with a real hierarchy: the subject
   large and tracked, the byline small and quiet. */
#header h1 {
  color: var(--ink) !important;
  display: block !important;
  font-size: clamp(1.6rem, 3.6vw, 2.1rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.15 !important;
  margin: 0;
  text-transform: uppercase;
}

/* Absolute sizes rather than nested ems: the title is `<strong>Subject</strong>
   byline` inside one <a>, and chaining relative sizes through both made the
   subject collapse. */
#header h1 a {
  border: 0;
  color: var(--ink);
  display: block;
  font-size: 0.72rem;
  font-weight: 300;
  letter-spacing: 0.18em;
  text-decoration: none;
}

#header h1 a strong {
  display: block;
  font-size: clamp(1.6rem, 3.6vw, 2.1rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  margin-bottom: 0.3rem;
}

#header nav ul { display: flex; gap: 1.5rem; list-style: none; margin: 0; padding: 0; }
#header nav li { padding: 0; }

/* The underline grows from nothing, which is the one flourish this design uses. */
#header nav a {
  border: 0 !important;
  color: var(--ink);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  position: relative;
  text-decoration: none;
  text-transform: uppercase;
}

#header nav a::after {
  background: var(--ink);
  bottom: -0.35rem;
  content: '';
  height: 1px;
  left: 0;
  max-width: 0;
  position: absolute;
  transition: max-width 400ms var(--ease);
  width: 100%;
}

#header nav a:hover::after,
#header nav a:focus-visible::after { max-width: 100%; }

/* ---- section headings -------------------------------------------------- */

.section-head {
  border-bottom: 1px solid var(--rule);
  display: flex;
  flex-basis: 100%;
  flex-wrap: wrap;
  gap: 0.5rem 2.5rem;
  justify-content: space-between;
  margin: 3rem 0 1.25rem;
  padding-bottom: 0.9rem;
  width: 100%;
}

.section-head:first-child { margin-top: 2rem; }

.section-id {
  align-items: baseline;
  display: flex;
  gap: 0.7rem;
}

/* Equipment and credits sit beside the section title, so each band states its
   own rig and collaborators rather than one note standing for the whole site. */
.section-note {
  color: var(--ink-soft);
  font-size: 0.76rem;
  font-weight: 300;
  line-height: 1.6;
  max-width: 40rem;
  text-align: right;
}

.section-note p { margin: 0; }
.section-note .credits { color: var(--ink-faint); }

@media (max-width: 900px) {
  .section-note { text-align: left; }
}

.section-head h2 {
  color: var(--ink);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  margin: 0;
  text-transform: uppercase;
}

/* The count is information — how many frames in this band — not decoration. */
.section-head .count {
  color: var(--ink-faint);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

/* ---- justified rows ---------------------------------------------------- */

#main {
  align-items: flex-start;
  background: none !important;
  display: flex !important;
  filter: none !important;
  flex-wrap: wrap;
  gap: var(--gap);
  padding: 0 0 4rem;
}

/* Absorbs leftover space so a partial last row keeps honest proportions instead
   of stretching one frame across the full width. The large flex-grow wins the
   remaining space; the flex-basis keeps it from claiming space in a full row. */
#main::after {
  content: '';
  flex: 999999 1 0;
  height: 0;
  min-width: 0;
}

#main .thumb {
  background: none;
  flex: var(--ratio, 1.5) 1 calc(var(--ratio, 1.5) * var(--row-h));
  height: auto !important;
  margin: 0;
  min-height: 0 !important;
  opacity: 1 !important;
  /* Visible, not hidden: the caption sits below the frame, and clipping the
     article to the row height cut it off entirely. The image wrapper does the
     clipping instead, so the hover zoom is still contained. */
  overflow: visible;
  pointer-events: auto !important;
  position: relative;
  /* Two clamps, both needed. max-height stops a sparse row from inflating its
     frames past the target; max-width stops a lone frame on the final row from
     stretching across the whole page (the ::after absorber has height 0, so
     flexbox still lets that last item claim the full line). */
  max-width: calc(var(--ratio, 1.5) * var(--row-h) * 1.4);
  transition: opacity 300ms var(--ease);
  transition-delay: 0s !important;
  width: auto !important;
}

/* Upstream's bottom gradient existed to make white captions legible; captions now
   sit below the frame, so it is just haze. */
#main .thumb::after { display: none !important; }

#main .thumb > .image {
  background: none !important;
  /* Clipping and the row-height clamp live here rather than on the article, so
     the caption below is never cut off. */
  max-height: calc(var(--row-h) * 1.4);
  overflow: hidden;
  display: block;
  height: auto !important;
  left: auto !important;
  position: static !important;
  top: auto !important;
  width: 100% !important;
}

#main .thumb > .image > img {
  /* Beats the inline display:none that jQuery used to set. */
  display: block !important;
  height: auto;
  width: 100%;
  aspect-ratio: var(--ratio, 1.5);
  object-fit: cover;
  /* Deliberately NO transform and NO transition on the <img> itself. Safari 26.0
     silently drops a gain-map image to SDR when either is applied to it, so the
     hover zoom lives on the wrapper — same visual result, HDR intact. */
}

/* The zoom is applied to the wrapper, not the image. */
#main .thumb > .image {
  transform: scale(1);
  transition: transform 600ms var(--ease), filter 300ms var(--ease);
}

#main .thumb:hover > .image,
#main .thumb:focus-within > .image {
  transform: scale(1.05);
}

#main .thumb > .image:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -3px;
}

/* A true panorama takes the row to itself: at 3:1 or wider, sharing a row would
   squeeze it to a strip, and it has the pixels to justify the space. */
#main .thumb--pano {
  flex: 1 1 100%;
  max-height: 70vh;
  max-width: none;
}

#main .thumb--pano > .image { max-height: 70vh; }

/* A wide crop or triptych (around 2:1) still shares a row, but the flex basis
   lets it claim most of it rather than being compressed to the row height. */
#main .thumb--wide {
  flex-grow: calc(var(--ratio, 2) * 1.6);
  max-width: calc(var(--ratio, 2) * var(--row-h) * 1.6);
}

/* ---- captions ---------------------------------------------------------- */

/* Set below the frame rather than over it, so nothing covers the photograph. */
#main .thumb > .frame-title {
  bottom: auto;
  color: var(--ink);
  font-size: 0.78rem;
  font-weight: 600;
  left: auto;
  letter-spacing: 0.06em;
  margin: 0.6rem 0 0;
  padding: 0 0.1rem;
  pointer-events: auto;
  position: static;
  text-shadow: none;
  text-transform: uppercase;
}

#main .thumb > .frame-title a {
  border: 0;
  color: inherit;
  text-decoration: none;
}

#main .thumb > .frame-title a:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

#main .thumb > .frame-loc {
  bottom: auto;
  color: var(--ink-faint);
  display: block;
  font-size: 0.72rem;
  font-weight: 300;
  left: auto;
  margin: 0.1rem 0 0;
  padding: 0 0.1rem;
  position: static;
  text-shadow: none;
}

/* ---- lightbox ---------------------------------------------------------- */

.poptrox-popup {
  animation: wake 240ms var(--ease) both;
  background: var(--ground);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.4);
  min-height: 240px;
  min-width: 240px;
}

@keyframes wake {
  from { opacity: 0; transform: scale(0.99); }
  to { opacity: 1; transform: scale(1); }
}

/* Upstream's loader is a 0.25-opacity hairline in a 150px box: on a dark field a
   slow 1-3MB image looked like a dead grey square. */
.poptrox-popup .loader {
  height: 2.6em !important;
  margin: -1.3em 0 0 -1.3em !important;
  opacity: 0.8 !important;
  width: 2.6em !important;
}

/* The caption sat on white with white text — the same `strong { color: #fff }`
   inheritance that hid the page title — so it read as a blank white bar under the
   photograph. It now overlays the bottom of the image on a gradient, the way the
   upstream template did, instead of adding a band of its own. */
.poptrox-popup .caption {
  background: linear-gradient(to top,
              rgba(10, 12, 16, 0.82) 0%,
              rgba(10, 12, 16, 0.45) 55%,
              rgba(10, 12, 16, 0) 100%) !important;
  bottom: 0;
  color: rgba(255, 255, 255, 0.92) !important;
  font-size: 0.76rem;
  font-weight: 300;
  left: 0;
  line-height: 1.5;
  padding: 2.5rem 1.2rem 1rem !important;
  pointer-events: none;
  position: absolute !important;
  right: 0;
  width: auto !important;
}

/* Nothing to say — no plate. */
.poptrox-popup .caption:empty { display: none !important; }

.poptrox-popup .caption p { margin: 0; }

.poptrox-popup .caption strong {
  color: #fff !important;
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  margin-bottom: 0.2rem;
  text-transform: uppercase;
}

/* The EXIF row: camera, aperture, shutter, ISO, each with its icon. */
.poptrox-popup .caption .exif {
  color: rgba(255, 255, 255, 0.72);
  display: inline-flex;
  flex-wrap: wrap;
  font-variant-numeric: tabular-nums;
  gap: 0.25rem 1rem;
  letter-spacing: 0.02em;
}

.poptrox-popup .caption .exif .fa,
.poptrox-popup .caption .exif [class^="fa-"] {
  margin-right: 0.3rem;
  opacity: 0.75;
}

/* ---- decks: a shoot as a stack of cards -------------------------------- */

/* Closed, a deck occupies one frame's worth of space and the frames behind fan
   out at the corner — so it is obvious more exist without needing a badge to say
   so. Clicking unfolds it into the grid in place; the lightbox is a second click.
   The fan uses the same footprint as a single card so rows stay justified. */
.deck {
  cursor: pointer;
  flex: var(--ratio, 1.5) 1 calc(var(--ratio, 1.5) * var(--row-h));
  max-width: calc(var(--ratio, 1.5) * var(--row-h) * 1.4);
  position: relative;
  /* The fanned cards rotate beyond the article box, so the deck reserves room for
     the overhang and sits above its neighbours rather than colliding with them. */
  margin: 0 18px 34px 6px;
  z-index: 1;
}

/* Closed, the deck is a single frame-shaped box that the absolute cards fill. */
.deck:not(.is-open) {
  /* Padding reserves room for the label below the cards, which are absolutely
     positioned inside the content box. Positioning the label into the fan's
     overhang instead kept leaving it underneath the lowest card. */
  aspect-ratio: var(--ratio, 1.5);
  box-sizing: content-box;
  height: auto;
  padding-bottom: 3rem;
}

.deck:hover { z-index: 5; }

.deck:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 6px;
}

/* --- closed state --- */

/* Every frame is stacked at the same place; only the first three are visible,
   rotated slightly so the edges of the ones behind show. */
#main .deck:not(.is-open) > .deck-frame {
  /* Every card is absolute and fills the deck's content box, so they align
     exactly and stay clear of the label's reserved padding. */
  bottom: 3rem;
  height: auto;
  left: 0;
  max-height: none;
  max-width: none;
  position: absolute;
  top: 0;
  transition: transform 300ms var(--ease), box-shadow 300ms var(--ease);
  width: 100%;
}

#main .deck:not(.is-open) > .deck-frame:first-child { z-index: 3; }

#main .deck:not(.is-open) > .deck-frame:nth-child(n+2) {
  border: 3px solid var(--ground);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
}

#main .deck:not(.is-open) > .deck-frame:nth-child(2) { transform: rotate(2.4deg) translate(7px, 5px); z-index: 2; }
#main .deck:not(.is-open) > .deck-frame:nth-child(3) { transform: rotate(-1.9deg) translate(-5px, 9px); z-index: 1; }

#main .deck:not(.is-open) > .deck-frame:nth-child(n+4) { opacity: 0; pointer-events: none; }

/* Fan wider on hover so it reads as "there is more here". */
#main .deck:not(.is-open):hover > .deck-frame:nth-child(2),
#main .deck:not(.is-open):focus-visible > .deck-frame:nth-child(2) {
  transform: rotate(3.6deg) translate(12px, 6px);
}

#main .deck:not(.is-open):hover > .deck-frame:nth-child(3),
#main .deck:not(.is-open):focus-visible > .deck-frame:nth-child(3) {
  transform: rotate(-3.2deg) translate(-9px, 12px);
}

/* Captions belong to the individual frames, so hide them while stacked — only
   the deck's own label applies to the group. */
.deck:not(.is-open) .frame-title,
.deck:not(.is-open) .frame-loc { display: none !important; }

/* The image inside a stacked frame must not intercept the click: the whole deck
   is one target until it is open. */
.deck:not(.is-open) .image { pointer-events: none; }

/* Stacked cards share one footprint — the deck's own aspect-ratio, taken from its
   first frame — so each card has to fill that box regardless of its own shape.
   The frames are absolutely positioned and stretched to the deck, but the .thumb
   rules these elements also match pin the image to `aspect-ratio: var(--ratio)`
   and clamp it to `--row-h * 1.4`. For a portrait frame in a landscape deck those
   two demands conflict: the image lays out 999px tall inside a 448px box and the
   overflow is clipped from the bottom, so a vertical photo shows as a horizontal
   band through the middle of the stack. Filling the card and cropping centrally is
   the correct behaviour for a pile of cards — the full frame is one click away. */
#main .deck:not(.is-open) > .deck-frame > .image {
  height: 100% !important;
  max-height: none;
}

#main .deck:not(.is-open) > .deck-frame > .image > img {
  aspect-ratio: auto;
  height: 100%;
  object-position: center;
  width: 100%;
}

.deck-label {
  bottom: 0;
  color: var(--ink);
  display: flex;
  gap: 0.5rem;
  left: 0;
  padding-top: 0.6rem;
  position: absolute;
  transform: none;
  z-index: 6;
}

.deck-name {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.deck-count {
  color: var(--ink-faint);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}

.deck-count::before { content: '· '; }

.deck:not(.is-open) .deck-collapse { display: none; }

/* --- open state --- */

/* Unfolded, the deck stops being a single card and becomes its own justified row
   of frames, which is why it takes the full width. */
.deck.is-open {
  cursor: default;
  margin: 0;
  display: flex;
  flex: 1 1 100%;
  flex-wrap: wrap;
  gap: var(--gap);
  max-width: none;
  padding-top: 2.4rem;
}

#main .deck.is-open > .deck-frame {
  flex: var(--ratio, 1.5) 1 calc(var(--ratio, 1.5) * var(--row-h));
  max-width: calc(var(--ratio, 1.5) * var(--row-h) * 1.4);
  position: relative;
}

#main .deck.is-open > .deck-frame:nth-child(n+4) { opacity: 1; pointer-events: auto; }

.deck.is-open .deck-label {
  bottom: auto;
  padding: 0;
  top: 0;
  transform: none;
}

.deck-collapse {
  background: none;
  border: 0;
  /* Upstream draws its button frame with an inset box-shadow, not a border, so
     `border: 0` never removed it. It also forces height/line-height/padding for a
     full-size button, which this small uppercase label must opt out of. */
  box-shadow: none;
  height: auto;
  line-height: 1.4;
  /* Upstream styles buttons with white text for its dark theme, which on this
     light ground left an empty outline. */
  color: var(--ink-soft) !important;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.7rem;
  /* Signika's 600 reads as a clear step up at this size where 500 does not, and
     the tighter tracking keeps the uppercase word from smearing once it is bold. */
  font-weight: 600;
  letter-spacing: 0.1em;
  /* Padding rather than a right offset: the button is the click target, so the
     breathing room needs to be inside it, not a gap beside it. Without this the
     word sits flush against the content edge and the last letter gets clipped. */
  padding: 0.2rem 0.1rem 0.2rem 0.6rem;
  position: absolute;
  right: 0;
  text-transform: uppercase;
  top: 0;
  z-index: 4;
}

.deck-collapse:hover { color: var(--ink) !important; }

/* A mouse click leaves the button focused, and the default outline draws a hard
   box tight around the word. Keep a clearly visible ring for keyboard users and
   drop it for pointer users, which is exactly what :focus-visible distinguishes. */
.deck-collapse:focus { outline: none; }

.deck-collapse:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .deck > .deck-frame { transition: none !important; }
}

/* ---- lightbox caption (PhotoSwipe) ------------------------------------- */

/* Overlaid on the photograph rather than adding a band beneath it. */
.pswp-caption {
  background: linear-gradient(to top,
              rgba(8, 10, 14, 0.86) 0%,
              rgba(8, 10, 14, 0.45) 60%,
              rgba(8, 10, 14, 0) 100%);
  bottom: 0;
  color: rgba(255, 255, 255, 0.9);
  font-family: "Signika", sans-serif;
  font-size: 0.78rem;
  font-weight: 300;
  left: 0;
  padding: 3rem 1.6rem 1.2rem;
  pointer-events: none;
  position: absolute;
  right: 0;
  z-index: 10;
}

.pswp-caption:empty { display: none; }

.pswp-caption strong {
  color: #fff;
  display: block;
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.pswp-caption .place {
  color: rgba(255, 255, 255, 0.62);
  display: block;
  margin-top: 0.15rem;
}

/* Capture settings, each with its icon. Absent on deep-sky stacks, which carry
   no EXIF — the row simply does not render. */
.pswp-caption .exif {
  color: rgba(255, 255, 255, 0.72);
  display: flex;
  flex-wrap: wrap;
  font-variant-numeric: tabular-nums;
  gap: 0.2rem 1.1rem;
  margin-top: 0.5rem;
}

.pswp-caption .exif i { margin-right: 0.35rem; opacity: 0.7; }

.pswp__counter {
  font-family: "Signika", sans-serif;
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
}


/* ---- global filmstrip -------------------------------------------------- */

/* Every photograph on the page, so this is site-wide navigation rather than
   navigation within whichever group was opened. */
.pswp-strip {
  align-items: center;
  bottom: 0;
  display: flex;
  gap: 6px;
  left: 0;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 10px 14px 12px;
  position: absolute;
  right: 0;
  scrollbar-width: none;
  z-index: 12;
  background: linear-gradient(to top, rgba(8,10,14,0.88), rgba(8,10,14,0));
}

.pswp-strip::-webkit-scrollbar { display: none; }

.pswp-strip__cell {
  background-color: rgba(255, 255, 255, 0.08);
  background-position: center;
  background-size: cover;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
  flex: 0 0 auto;
  height: 46px;
  opacity: 0.5;
  padding: 0;
  transition: opacity 180ms var(--ease), transform 180ms var(--ease);
  width: 66px;
}

.pswp-strip__cell:hover { opacity: 0.85; }

.pswp-strip__cell.is-current {
  box-shadow: 0 0 0 2px #fff;
  opacity: 1;
  transform: translateY(-2px);
}

.pswp-strip__cell:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* Keep the caption clear of the strip. */
.pswp-caption { padding-bottom: 5.2rem; }

@media (max-width: 736px) {
  .pswp-strip__cell { height: 38px; width: 54px; }
  .pswp-caption { padding-bottom: 4.4rem; }
}

@media (prefers-reduced-motion: reduce) {
  .pswp-strip__cell { transition: none; }
}

/* ---- copyright notice on right-click ----------------------------------- */

/* Appears where the context menu would have, states ownership, and fades. */
.copyright-toast {
  background: rgba(17, 17, 17, 0.92);
  border-radius: 4px;
  color: #fff;
  font-size: 0.72rem;
  font-weight: 400;
  left: 0;
  letter-spacing: 0.04em;
  opacity: 0;
  padding: 0.5rem 0.8rem;
  pointer-events: none;
  position: fixed;
  top: 0;
  transform: translateY(4px);
  transition: opacity 160ms var(--ease), transform 160ms var(--ease);
  white-space: nowrap;
  z-index: 20050;
}

.copyright-toast.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Photographs are not selectable, so a drag does not start a text selection that
   would then carry the image. Captions stay selectable. */
#main .thumb > .image,
#main .thumb img,
.poptrox-popup img {
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  -webkit-user-select: none;
  user-select: none;
}

@media (prefers-reduced-motion: reduce) {
  .copyright-toast { transition: none; }
}

/* ---- footer ------------------------------------------------------------ */

/* Upstream styles `.panel` as a fixed drawer that slides up from off-screen
   (`position: fixed; transform: translateY(100vh)`), opened by the About link.
   Making it a normal footer requires undoing the transform as well as the
   positioning — leaving the transform in place pushed it a full viewport height
   down the page and left ~900px of blank space above it. */
#footer {
  background: none !important;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 300;
  margin-top: 1rem;
  max-height: none !important;
  overflow: visible !important;
  padding: 2.5rem 0 4rem !important;
  position: static !important;
  transform: none !important;
  transition: none !important;
}

/* The drawer's close button has no meaning once the footer is part of the page. */
#footer > .closer { display: none !important; }

#footer h2 {
  color: var(--ink);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  margin: 0 0 0.75rem;
  text-transform: uppercase;
}

#footer .inner.split { display: grid; gap: 2.5rem; }

@media (min-width: 900px) {
  #footer .inner.split { grid-template-columns: 1.4fr 1fr; }
}

#footer section { margin: 0 0 1.75rem; }
#footer p { line-height: 1.7; margin: 0 0 0.6rem; max-width: 44rem; }
#footer a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
#footer .copyright { color: var(--ink-faint); font-size: 0.72rem; line-height: 1.6; }
#footer .icons a { border: 0; color: var(--ink); }

#footer .button,
#footer .actions .button {
  background: var(--ink) !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  color: var(--ground) !important;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  padding: 0.85rem 1.5rem !important;
  text-transform: uppercase;
}

/* ---- responsive -------------------------------------------------------- */

@media (max-width: 980px) {
  :root { --row-h: 240px; }
}

@media (max-width: 736px) {
  :root { --row-h: 200px; }
  #header { padding-top: 2rem !important; }
  #main .thumb { flex-basis: 100%; max-height: none; }
  #main .thumb--pano { max-height: none; }
}


/* ---- from the reference-template audit --------------------------------- */

/* No blue flash when tapping a thumbnail on iOS. */
#main .thumb,
#main .thumb a,
#main .thumb img { -webkit-tap-highlight-color: transparent; }

/* Safari aliases transformed images; this is the fix, applied to the elements
   that actually get scaled (the reference template declared it but put it on the
   avatar instead of the gallery). */
#main .thumb > .image > img {
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  will-change: transform;
}

/* Keyboard focus must stay visible — the reference template used
   `focus:outline-none` with no replacement, which removes it outright. */
.pswp button:focus-visible,
#header nav a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* ---- accessibility ----------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  #main .thumb,
  #main .thumb > .image > img,
  .poptrox-popup {
    animation: none !important;
    transition: none !important;
  }
  #main .thumb:hover > .image > img { transform: none; }
}
