/*
  gallery.css
  Shared stylesheet for the generated gallery pages (edinburgh.html,
  istanbul.html). Same tokens, bar, buttons, viewer and footer as
  landing.css, so the galleries read as the same site.

  The gallery itself ("Model B"): every row is one third of the gallery's
  width tall (--row-h). A 3:2 landscape is 1.5 row-heights wide and a 2:3
  portrait 2/3, so two landscapes fill a row exactly and four portraits
  nearly do. Which photos share a row was decided by the generator; here
  each row is just a flex row of fixed-size figures, aligned left, right,
  centred or with the gap in the middle via a class. Below 700px the rows
  become a single full-width column.
*/

:root {
  --base-grad: linear-gradient(
    25deg,
    #ee7752,
    #ff5e00,
    #e73c7e,
    #d90ead,
    #23a6d5,
    #70e0ec,
    #23d5ab,
    #00ff44
  );

  --hero-bg: #0d0b16;
  --hero-fg: #f6f3fb;
  --hero-fg-2: rgba(246, 243, 251, 0.72);
  --hero-fg-3: rgba(246, 243, 251, 0.5);
  --hero-line: rgba(246, 243, 251, 0.16);

  --turn-ease: cubic-bezier(0.22, 0.85, 0.25, 1);

  /* Page measure. */
  --max: 1280px;
  --pad: clamp(16px, 4vw, 48px);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  overflow-x: hidden;
}

body {
  margin: 0;
  background: var(--hero-bg);
  color: var(--hero-fg);
  font-family: "Poppins", system-ui, sans-serif;
  overflow-x: hidden;
}

body.lb-open {
  overflow: hidden;
}

@keyframes Gradient {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

/* ---------- Scroll reveal ---------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.8s ease, transform 0.8s ease;
  transition-delay: var(--reveal-delay, 0s);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    transition: none;
    transform: none;
    opacity: 1;
  }
}

/* ======================================================================
   Bar (sticky here -- it's a long page)
   ====================================================================== */

.gBar {
  position: sticky;
  top: 0;
  z-index: 20;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--pad);
  background: rgba(13, 11, 22, 0.62);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--hero-line);
}

.arcBrand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: var(--hero-fg);
  text-decoration: none;
}

/* Wordmark in the brand gradient; two inline-block words so it can break
   onto two lines on phones. */
.arcWordmark {
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: var(--base-grad);
  background-size: 400% 400%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: Gradient 15s ease infinite;
}

.arcWordmark > span {
  display: inline-block;
  white-space: nowrap;
}

.arcNav {
  display: flex;
  gap: clamp(16px, 2.4vw, 36px);
}

.arcNav a {
  position: relative;
  padding: 6px 0;
  color: var(--hero-fg-2);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: color 0.25s ease;
}

.arcNav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--base-grad);
  background-size: 400% 400%;
  animation: Gradient 15s ease infinite;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--turn-ease);
}

.arcNav a:hover,
.arcNav a:focus-visible {
  color: var(--hero-fg);
}

.arcNav a:hover::after,
.arcNav a:focus-visible::after {
  transform: scaleX(1);
}

@media (max-width: 640px) {
  /* "Ben Jenkins" over "Photography": a grid, not a width cap, so the box
     always covers both words (text outside a background-clip: text box
     has no gradient behind it and disappears). */
  .arcWordmark {
    display: inline-grid;
    gap: 1px;
    font-size: 11px;
    letter-spacing: 0.1em;
  }

  .arcNav {
    gap: 14px;
  }

  .arcNav a {
    font-size: 12px;
    letter-spacing: 0.1em;
  }
}

/* The slow pulse shared by every bloom on the site. */
@keyframes arcGlow {
  from {
    opacity: 0.75;
    scale: 1;
  }
  to {
    opacity: 1;
    scale: 1.06;
  }
}

/* Small gradient label. */
.arcEyebrow {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  background: var(--base-grad);
  background-size: 400% 400%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: Gradient 15s ease infinite;
}

/* ======================================================================
   Page head: eyebrow, the big title, intro columns
   ====================================================================== */

/* The blooms behind the title and the section headers reach past the
   page's right edge. Clipped here (clip, not hidden, so this doesn't
   become a scroll container): otherwise they widen the document, and on
   mobile browsers that widens the layout viewport that fixed elements
   like the jump buttons are anchored to -- pushing them off-screen. */
.gPage {
  position: relative;
  overflow-x: clip;
}

/* No overflow clipping here: the bloom is meant to spill past the content
   column into the page margins and down behind the first section. The
   page-level overflow-x: clip on .gPage stops it widening the document. */
.gHead {
  position: relative;
  isolation: isolate;
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(48px, 8vh, 96px) var(--pad) clamp(28px, 4vh, 48px);
}

.gHead::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 28%;
  top: 38%;
  width: min(1100px, 130vw);
  height: 640px;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    rgba(217, 14, 173, 0.32),
    rgba(231, 60, 126, 0.16) 36%,
    rgba(35, 166, 213, 0.1) 62%,
    transparent 100%
  );
  pointer-events: none;
  animation: arcGlow 12s ease-in-out infinite alternate;
}

.gTitle {
  margin: 10px 0 clamp(24px, 4vh, 48px) -0.04em;
  font-size: clamp(56px, 13vw, 190px);
  font-weight: 600;
  line-height: 0.92;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  text-wrap: balance;
}

.gIntro {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: clamp(24px, 4vw, 64px);
  padding-top: 24px;
  border-top: 1px solid var(--hero-line);
}

.gTagline {
  font-family: "Baskerville", "Georgia", serif;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(20px, 2vw, 28px);
  letter-spacing: 0.01em;
  margin-bottom: 12px;
}

.gDesc {
  max-width: 62ch;
  font-size: clamp(15px, 1.1vw, 17px);
  line-height: 1.65;
  color: var(--hero-fg-2);
  text-wrap: pretty;
}

.gMeta {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px 22px;
  align-content: start;
  padding-left: clamp(24px, 4vw, 64px);
  border-left: 1px solid var(--hero-line);
  font-size: 14px;
}

.gMeta dt {
  padding-top: 2px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--hero-fg-3);
}

.gMeta dd {
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.gToc {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  font-weight: 400;
}

.gToc a {
  color: var(--hero-fg-2);
  text-decoration: none;
  border-bottom: 1px solid var(--hero-line);
  transition: color 0.25s ease, border-color 0.25s ease;
}

.gToc a:hover,
.gToc a:focus-visible {
  color: var(--hero-fg);
  border-color: var(--hero-fg);
}

.gHint {
  margin-top: 28px;
  font-size: 12px;
  color: var(--hero-fg-3);
}

@media (max-width: 699px) {
  .gIntro {
    grid-template-columns: 1fr;
  }

  .gMeta {
    padding-left: 0;
    padding-top: 20px;
    border-left: 0;
    border-top: 1px solid var(--hero-line);
  }
}

/* ======================================================================
   Gallery
   ====================================================================== */

.gGallery {
  /* Container so the row height can be written in terms of this box's
     own inner width (cqw), whatever the viewport. */
  container-type: inline-size;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad) clamp(64px, 8vh, 120px);
  --gap: clamp(10px, 1.4cqw, 18px);
  /* Two landscapes (1.5 + 1.5 row-heights) plus one gap span the width. */
  --row-h: calc((100cqw - var(--gap)) / 3);
}

.gSection {
  position: relative;
  isolation: isolate;
  padding-top: clamp(40px, 6vh, 72px);
}

/* A smaller cousin of the title's bloom behind each section's description.
   It belongs to the section (not the header) and sits at negative z-index
   inside it, so the section's own photos paint over it and it never spills
   onto the previous section's rows. */
.gSection::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  right: 0;
  width: min(820px, 90vw);
  height: 440px;
  translate: 12% -18%;
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    rgba(217, 14, 173, 0.2),
    rgba(231, 60, 126, 0.1) 40%,
    rgba(35, 166, 213, 0.07) 65%,
    transparent 100%
  );
  pointer-events: none;
  animation: arcGlow 12s ease-in-out infinite alternate;
}

/* Alternate the bloom's side and hue so a long page doesn't strobe. */
.gSection:nth-child(even)::before {
  right: auto;
  left: 0;
  translate: -12% -18%;
  background: radial-gradient(
    closest-side,
    rgba(35, 166, 213, 0.2),
    rgba(112, 224, 236, 0.08) 42%,
    rgba(217, 14, 173, 0.06) 68%,
    transparent 100%
  );
}

/* Description gets ~2.1 : 1 of the header's width (was 1.4 : 1). */
.gSectionHead {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.1fr);
  gap: clamp(16px, 3vw, 48px);
  align-items: end;
  padding-bottom: 24px;
  margin-bottom: clamp(20px, 2.4cqw, 34px);
  border-bottom: 1px solid var(--hero-line);
}

/* "01 / 07" flanked by up/down arrows to the neighbouring sections (the
   first points to the page top, the last to the end). */
.gSectionNav {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.gSectionArrow,
.gJump a {
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--hero-line);
  background: rgba(255, 255, 255, 0.06);
  color: var(--hero-fg-2);
  text-decoration: none;
  transition: background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
  -webkit-tap-highlight-color: transparent;
}

.gSectionArrow {
  width: 26px;
  height: 26px;
}

.gSectionArrow:hover,
.gSectionArrow:focus-visible,
.gJump a:hover,
.gJump a:focus-visible {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.4);
  color: var(--hero-fg);
}

.gSectionArrow:focus-visible,
.gJump a:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* Bottom-right jump buttons: top of page / end of page. Hidden while the
   viewer is open so they don't sit on top of its controls. */
.gJump {
  position: fixed;
  right: clamp(12px, 2vw, 28px);
  bottom: clamp(12px, 2vw, 28px);
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.gJump a {
  width: 40px;
  height: 40px;
  background: rgba(13, 11, 22, 0.55);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

body.lb-open .gJump {
  display: none;
}

.gSectionHead h2 {
  margin-top: 8px;
  font-size: clamp(30px, 3.4vw, 46px);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.gSectionTag {
  margin-top: 6px;
  font-family: "Baskerville", "Georgia", serif;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(16px, 1.4vw, 20px);
  color: var(--hero-fg-2);
}

.gSectionDesc {
  max-width: 84ch;
  font-size: clamp(14px, 1vw, 16px);
  line-height: 1.65;
  color: var(--hero-fg-2);
  text-wrap: pretty;
}

/* Rows */

.gRow {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
  margin-bottom: clamp(20px, 2.4cqw, 34px);
}

.gRow--right {
  justify-content: flex-end;
}

.gRow--between {
  justify-content: space-between;
}

.gRow--center {
  justify-content: center;
}

.gFigure {
  flex: none;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.gFigure--l {
  width: calc(var(--row-h) * 1.5);
}

.gFigure--p {
  width: calc(var(--row-h) * 2 / 3);
}

/* The photo box has the photo's own aspect ratio, so object-fit: cover
   never has anything to crop (every file is 3:2 or 2:3 to within 0.05%). */
.gPhoto {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  padding: 0;
  border: 0;
  background: #1a1526;
  border-radius: clamp(8px, 1cqw, 14px);
  overflow: hidden;
  cursor: zoom-in;
  box-shadow: 0 20px 40px -24px rgba(0, 0, 0, 0.8);
  transition: transform 0.35s ease, box-shadow 0.35s ease;
  -webkit-tap-highlight-color: transparent;
}

.gFigure--p .gPhoto {
  aspect-ratio: 2 / 3;
}

.gPhoto:hover {
  transform: translateY(-4px);
  box-shadow: 0 28px 48px -22px rgba(0, 0, 0, 0.85), 0 0 0 2px rgba(255, 255, 255, 0.3);
}

.gPhoto:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

.gPhoto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}

/* Fixed two-line height so the bottom of every row stays level whether a
   caption wraps or not. */
.gFigure figcaption {
  min-height: 3em;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--hero-fg-3);
}

/* Phones: one column, every photo full width. */
@media (max-width: 699px) {
  .gSectionHead {
    grid-template-columns: 1fr;
    align-items: start;
  }

  .gRow {
    flex-direction: column;
    gap: 28px;
    margin-bottom: 28px;
  }

  .gFigure--l,
  .gFigure--p {
    width: 100%;
  }

  .gFigure figcaption {
    min-height: 0;
  }
}

/* ======================================================================
   Enlarged view (same as the landing page)
   ====================================================================== */

.arcLightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  grid-template-columns: 56px 1fr 56px;
  align-items: center;
  justify-items: center;
  gap: 8px;
  padding: 0 clamp(8px, 2vw, 28px);
  background: rgba(9, 7, 16, 0.8);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  color: var(--hero-fg);
  animation: lbFade 0.35s ease backwards;
}

.arcLightbox[hidden] {
  display: none;
}

@keyframes lbFade {
  from {
    opacity: 0;
  }
}

.lbFigure {
  grid-column: 2;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  max-width: 100%;
}

.lbFrame {
  position: relative;
  padding: clamp(5px, 0.8vh, 9px);
  border-radius: 14px;
}

.lbFrame::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--base-grad);
  background-size: 400% 400%;
  animation: Gradient 15s ease infinite, lbFrameIn 0.7s ease 0.25s backwards;
}

@keyframes lbFrameIn {
  from {
    opacity: 0;
  }
}

.lbImg {
  --lb-ar: 1.5;
  position: relative;
  display: block;
  height: min(80svh, calc((100vw - 190px) / var(--lb-ar)));
  width: auto;
  aspect-ratio: var(--lb-ar);
  object-fit: cover;
  border-radius: 9px;
  background: #1a1526;
  cursor: zoom-out;
}

.lbCaption {
  display: flex;
  align-items: baseline;
  gap: 18px;
  font-size: 13px;
  color: var(--hero-fg-2);
  text-align: center;
}

.lbCount {
  color: var(--hero-fg-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.lbClose,
.lbNav {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--hero-line);
  background: rgba(255, 255, 255, 0.07);
  color: var(--hero-fg);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background 0.25s ease, border-color 0.25s ease;
  -webkit-tap-highlight-color: transparent;
}

.lbClose {
  position: fixed;
  top: 16px;
  right: 16px;
}

.lbNav--prev {
  grid-column: 1;
}

.lbNav--next {
  grid-column: 3;
}

.lbClose:hover,
.lbNav:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.4);
}

.lbClose:focus-visible,
.lbNav:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

@media (max-width: 640px) {
  .arcLightbox {
    grid-template-columns: 1fr;
    padding: 0 16px;
  }

  .lbFigure {
    grid-column: 1;
  }

  .lbImg {
    height: min(72svh, calc((100vw - 46px) / var(--lb-ar)));
  }

  .lbCaption {
    flex-direction: column;
    gap: 6px;
  }

  .lbNav {
    position: fixed;
    bottom: 18px;
  }

  .lbNav--prev {
    left: 18px;
  }

  .lbNav--next {
    right: 18px;
  }
}

::view-transition-group(arc-photo) {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
}

::view-transition-old(arc-photo),
::view-transition-new(arc-photo) {
  animation-duration: 0.6s;
  height: 100%;
  width: 100%;
  object-fit: cover;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.5s;
}

/* ======================================================================
   Footer
   ====================================================================== */

.footer {
  border-top: 1px solid var(--hero-line);
  padding: clamp(28px, 4vh, 48px) var(--pad);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.footerText {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px 32px;
  text-align: center;
}

.footerText h3 {
  font-size: clamp(15px, 1.4vw, 20px);
  font-weight: 500;
}

.footerText h3 a {
  color: var(--hero-fg);
  text-decoration: none;
  border-bottom: 1px solid var(--hero-line);
  transition: border-color 0.25s ease;
}

.footerText h3 a:hover,
.footerText h3 a:focus-visible {
  border-color: var(--hero-fg);
}

.footerText h1 {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--hero-fg-3);
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .arcLightbox,
  .gHead::before,
  .gSection::before {
    animation: none;
  }

  .lbFrame::before {
    animation: Gradient 15s ease infinite;
  }

  .gPhoto {
    transition: none;
  }

  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}
