/* ============================================
   Sabali — Isaac Osei Jones
   Wetwood / Light Accent palette, 4-role type system
   ============================================ */

:root {
  /* Wetwood / Light Accent palette */
  --bg: #f5efe4;         /* Light Accent — warm cream ground */
  --bg-alt: #eee3d2;      /* deeper cream for banded surfaces / placeholder tiles */
  --ink: #33241a;         /* Wetwood — deep wet-oak brown, primary text */
  --ink-dim: #7a6a5c;      /* muted warm brown-gray, secondary text */
  --accent: #9c6b3e;      /* warm caramel — bridges Wetwood and the light ground */
  --accent-hover: #7e5530;
  --line: rgba(51, 36, 26, 0.16);

  /* EDIT: URW DIN, Shapiro Base, and Sofia Pro are commercial fonts not on
     Google Fonts — self-host once the licensed files are supplied:
       @font-face { font-family: "URW DIN";    src: url("assets/fonts/URWDIN-Bold.woff2") format("woff2"); font-weight: 700; }
       @font-face { font-family: "Shapiro";    src: url("assets/fonts/ShapiroBase-Light.woff2") format("woff2"); font-weight: 300; }
       @font-face { font-family: "Sofia Pro";  src: url("assets/fonts/SofiaPro-Light.woff2") format("woff2"); font-weight: 300; }
       @font-face { font-family: "Sofia Pro";  src: url("assets/fonts/SofiaPro-Regular.woff2") format("woff2"); font-weight: 400; }
     then swap the family names below. Archivo / Plus Jakarta Sans / Manrope
     stand in for now as the closest free matches. */
  --font-heading: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;   /* URW DIN */
  --font-subtitle: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;           /* Shapiro Base */
  --font-body: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;       /* Sofia Pro */

  --max: 1080px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 300;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1.15;
  margin: 0;
  color: var(--ink);
  text-wrap: balance;
}

section[id] { scroll-margin-top: 80px; }

.section { padding: clamp(56px, 9vw, 104px) 24px; }
.section-inner { max-width: var(--max); margin: 0 auto; }

/* Whichever section comes first on a page (there is no hero) needs extra top
   padding to clear the fixed header. Matching on position rather than naming
   the sections means reordering them — or deleting the temporary exhibition
   block — cannot leave the new first section tucked under the header. */
body > section:first-of-type { padding-top: clamp(104px, 15vw, 168px); }

.kicker {
  font-family: var(--font-subtitle);
  font-size: 0.75rem;
  font-weight: 300;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 12px;
}
h2 { font-size: clamp(1.7rem, 3.4vw, 2.3rem); }
h1.page-title { font-size: clamp(2.2rem, 5vw, 3.2rem); }

.subtitle {
  font-family: var(--font-subtitle);
  font-weight: 300;
  font-size: clamp(1rem, 2vw, 1.15rem);
  color: var(--ink-dim);
  margin: 14px 0 0;
  max-width: 52ch;
}

/* ---------- Specifications ---------- */
.specs { margin: 26px 0 4px; border-top: 1px solid var(--line); }
.spec-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 20px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
}
.spec-row dt {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
  white-space: nowrap;
}
.spec-row dd {
  margin: 0;
  font-size: 0.92rem;
  color: var(--ink);
  text-align: right;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  padding: 14px 28px;
  border-radius: 2px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
  cursor: pointer;
}
.btn-primary {
  background: var(--accent);
  color: #ffffff;
  border: 1px solid var(--accent);
}
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-ghost {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line);
}
.btn-ghost:hover { border-color: var(--ink); }
.btn-large { padding: 16px 38px; font-size: 0.95rem; margin-top: 6px; }

/* The exhibition's two actions sit side by side, on phones as well as on
   desktop. wrap is a safety net only: the mobile rules below shrink the tiles
   and labels enough to keep both on one line at 360px. */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px clamp(16px, 2.5vw, 28px);
}
.cta-row .icon-cta { margin-top: 0; }



/* ---------- Icon call to action ----------
   The site's CTA pattern, shared by the book's buy link and the exhibition's
   two actions: a filled arrow tile beside the label. The disc carries the
   weight on its own, which matters on phones — it looks the same there as it
   does at rest on a desktop, where hover springs it larger and draws the
   underline. */
.icon-cta {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  margin-top: 26px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.icon-cta-dot {
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  /* 2px to match .btn — square, but not a hard corner against the soft type. */
  border-radius: 2px;
  background: var(--accent);
  color: #ffffff;
  display: grid;
  place-items: center;
  transition: transform 0.45s cubic-bezier(0.34, 1.4, 0.64, 1), background 0.3s ease;
}
.icon-cta-dot svg {
  width: 17px;
  height: 17px;
  transition: transform 0.45s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.icon-cta:hover .icon-cta-dot,
.icon-cta:focus-visible .icon-cta-dot {
  transform: scale(1.12);
  background: var(--accent-hover);
}
.icon-cta:hover .icon-cta-dot svg,
.icon-cta:focus-visible .icon-cta-dot svg { transform: translateX(3px); }

.icon-cta-label { position: relative; padding-bottom: 4px; }
.icon-cta-label::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 0;
  background: var(--ink);
  transition: width 0.45s cubic-bezier(0.65, 0, 0.35, 1);
}
.icon-cta:hover .icon-cta-label::after,
.icon-cta:focus-visible .icon-cta-label::after { width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .icon-cta-dot, .icon-cta-dot svg, .icon-cta-label::after { transition: none; }
  .icon-cta:hover .icon-cta-dot, .icon-cta:focus-visible .icon-cta-dot,
  .icon-cta:hover .icon-cta-dot svg, .icon-cta:focus-visible .icon-cta-dot svg {
    transform: none;
  }
}

/* ---------- Header / Nav ---------- */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  padding: 22px 24px;
  transition: background 0.2s ease, padding 0.2s ease, border-color 0.2s ease;
  border-bottom: 1px solid transparent;
}
.site-header.scrolled {
  background: rgba(245, 239, 228, 0.94);
  backdrop-filter: blur(6px);
  padding: 16px 24px;
  border-bottom-color: var(--line);
}

.nav-inner {
  max-width: var(--max);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.brand { display: flex; align-items: center; }
.brand-logo { height: 52px; width: auto; display: block; }

.main-nav {
  display: flex;
  align-items: center;
  gap: 30px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.88rem;
}
.main-nav a { color: var(--ink-dim); transition: color 0.15s ease; }
.main-nav a:hover,
.main-nav a[aria-current="page"] { color: var(--ink); }
.nav-ig { display: flex; align-items: center; }

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px;
}
.nav-toggle span {
  width: 22px; height: 1px;
  background: var(--ink);
  transition: transform 0.2s ease, opacity 0.2s ease;
}

a:focus-visible,
.btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 3px;
}

/* ---------- Accessibility ---------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Two-column sections ---------- */
.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 6vw, 72px);
  align-items: start;
}
.col-text p { color: var(--ink-dim); max-width: 52ch; }

/* ---------- Rotatable 3D book ----------
   A real cuboid: front, back, spine, page edges, head and tail. Proportions
   follow the printed book (21 x 28 cm), with thickness as a share of width.
   --spin is driven by JS (drag / the buttons below the book). */
.book-viewer {
  --bw: clamp(200px, 40vw, 300px);
  --bh: calc(var(--bw) * 28 / 21);
  /* Spine thickness, measured off the spine photo: the flattened spine is
     23.8x longer than it is wide, so at 21x28cm the book is ~1.2cm thick.
     Keeping this exact means the spine photo renders undistorted. */
  --bt: calc(var(--bw) * 0.056);
  --spin: 20deg;
  --tilt: -4deg;
}

.book-stage {
  position: relative;
  height: calc(var(--bh) + 60px);
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 1900px;
  cursor: grab;
  touch-action: pan-y;              /* horizontal drag rotates, vertical still scrolls */
  outline-offset: 6px;
}
.book-stage.is-dragging { cursor: grabbing; }

.book {
  position: relative;
  width: var(--bw);
  height: var(--bh);
  transform-style: preserve-3d;
  transform: rotateX(var(--tilt)) rotateY(var(--spin));
  transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.book.is-dragging { transition: none; }

.book-face {
  position: absolute;
  backface-visibility: hidden;
  background: var(--bg-alt);
}

/* Covers */
.book-front,
.book-back {
  top: 0; left: 0;
  width: var(--bw);
  height: var(--bh);
  object-fit: cover;
}
.book-front { transform: translateZ(calc(var(--bt) / 2)); }
.book-back  { transform: rotateY(180deg) translateZ(calc(var(--bt) / 2)); }

/* Spine (left edge) and fore-edge pages (right edge) */
.book-spine,
.book-pages {
  top: 0;
  left: calc((var(--bw) - var(--bt)) / 2);
  width: var(--bt);
  height: var(--bh);
  overflow: hidden;
}
.book-spine {
  transform: rotateY(-90deg) translateZ(calc(var(--bw) / 2));
  background: var(--ink);          /* fallback if the photo fails to load */
}
.book-spine-img { width: 100%; height: 100%; object-fit: cover; }
/* Edge shading so the spine doesn't read as a flat sticker */
.book-spine::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgba(0, 0, 0, 0.22) 0%,
    rgba(0, 0, 0, 0) 26%,
    rgba(0, 0, 0, 0) 74%,
    rgba(0, 0, 0, 0.24) 100%);
  pointer-events: none;
}

.book-pages {
  transform: rotateY(90deg) translateZ(calc(var(--bw) / 2));
  background:
    repeating-linear-gradient(90deg,
      rgba(51, 36, 26, 0.16) 0px,
      rgba(51, 36, 26, 0.16) 0.5px,
      transparent 0.5px,
      transparent 2.5px),
    linear-gradient(90deg, #cdbfab 0%, #f3ece0 30%, #fbf7ef 60%, #d8ccba 100%);
}

/* Head and tail — the page block seen from above and below */
.book-top,
.book-bottom {
  left: 0;
  top: calc((var(--bh) - var(--bt)) / 2);
  width: var(--bw);
  height: var(--bt);
  background:
    repeating-linear-gradient(0deg,
      rgba(51, 36, 26, 0.14) 0px,
      rgba(51, 36, 26, 0.14) 0.5px,
      transparent 0.5px,
      transparent 2.5px),
    linear-gradient(180deg, #e7ddcc 0%, #fbf7ef 45%, #d9cdbb 100%);
}
.book-top    { transform: rotateX(90deg) translateZ(calc(var(--bh) / 2)); }
.book-bottom { transform: rotateX(-90deg) translateZ(calc(var(--bh) / 2)); }

/* Ground shadow, outside the 3D context so it stays put */
.book-shadow {
  position: absolute;
  bottom: 8px;
  left: 50%;
  width: calc(var(--bw) * 0.82);
  height: 22px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center,
    rgba(51, 36, 26, 0.34) 0%,
    rgba(51, 36, 26, 0.14) 45%,
    transparent 72%);
  filter: blur(6px);
  pointer-events: none;
}

.book-controls {
  display: flex;
  justify-content: center;
  margin-top: 6px;
}
/* Single affordance: signals the book turns, and steps through the views. */
.book-rotate {
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--ink-dim);
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.book-rotate:hover { color: var(--ink); border-color: var(--ink-dim); }
.book-rotate svg { transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1); }
.book-rotate:hover svg { transform: rotate(60deg); }

.book-rotate:focus-visible,
.book-stage:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .book-rotate svg { transition: none; }
  .book-rotate:hover svg { transform: none; }
}

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

/* ---------- Exhibition notice ----------
   TEMPORARY: this whole block, and the matching section in index.html, come
   out once the exhibition has been and gone. Nothing else depends on it.

   The date and venue are plain HTML text rather than words baked into the
   flyer image, so they are readable, searchable, and can be corrected here
   without re-exporting artwork. */

/* Shares .two-col with the book section below, so this text sits in the same
   right-hand column as the book's. The flyer fills its column rather than
   matching the book's width: the exhibition leads the page, and the poster is
   what carries it. */
.exhibition-flyer {
  width: 100%;
  margin: 0;
}

/* .two-col ranges its columns to the top, which suits the book and its long
   spec table. Here three short lines against a full-height poster would hang
   at the top of a tall gap, so this block centres instead. */
.exhibition { align-items: center; }
.exhibition-flyer img {
  display: block;
  width: 100%;
  height: auto;
  box-shadow: 0 22px 44px -26px rgba(51, 36, 26, 0.6);
}



/* ---------- Portfolio / gallery ---------- */
.portfolio-intro { color: var(--ink-dim); max-width: 60ch; }

.gallery-grid {
  margin-top: 48px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(28px, 5vw, 56px);
  align-items: start;
}

/* ---------- Framed print ----------
   Proportions taken from the supplied frame mockup: black moulding at ~1.9%
   of the frame's outer width and a white mat at ~8.4%, even on all four
   sides. No fixed aspect ratio, so portrait and landscape keep their shape. */
.framed { margin: 0; }

.framed-mat {
  /* One standard frame size for every print, at the A-series ratio the prints
     are actually sold in (A4-A1 are all 1:root-2). Mixed crops fill the
     opening, so every print reads identically across the site. */
  aspect-ratio: 1 / 1.414;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  padding: 7.5%;                                   /* minimum mat */
  border: clamp(5px, 0.7vw, 10px) solid #14120f;   /* moulding */
  box-shadow: 0 20px 34px -20px rgba(51, 36, 26, 0.5);
  transition: box-shadow 0.3s ease, transform 0.3s ease;
}
.framed-photo {
  display: block;
  width: 100%;
  height: 100%;
  /* Fills the opening so every print reads the same size. Costs a little of
     each crop (~6% off a 2:3, ~12% off a 4:5); 1:root-2 was chosen because it
     spreads that loss most evenly rather than taking ~17% off one pair. */
  object-fit: cover;
}

.framed:hover .framed-mat {
  transform: translateY(-3px);
  box-shadow: 0 28px 44px -22px rgba(51, 36, 26, 0.55);
}

.gallery-cta {
  display: flex;
  justify-content: center;
  margin-top: clamp(36px, 5vw, 56px);
}

@media (prefers-reduced-motion: reduce) {
  .framed-mat, .framed:hover .framed-mat { transition: none; transform: none; }
}

/* ---------- Editorial gallery (Lifestyle + Portraits) ----------
   Commissioned work, not prints for sale, so it deliberately breaks from the
   framed treatment on Wildlife: no moulding, no mat, no purchase link. Photos
   keep their own proportions — nothing is cropped, here or in the carousel.

   Two layouts from one set of markup: a horizontal carousel on desktop, and a
   vertical stack that animates in on phones (see the max-860px block below).
   Adding a photo is still just appending a <figure> to .editorial-track. */
.editorial-gallery { position: relative; margin-top: clamp(44px, 7vw, 80px); }

/* Native scroll does the work — momentum, trackpad and touch come free, and
   the JS only drives the arrows, the progress bar and the keyboard. */
.editorial-track {
  position: relative;          /* offsetParent for the slide maths in main.js */
  display: flex;
  gap: clamp(20px, 3vw, 36px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* The progress bar reports position, so the bar itself is redundant. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.editorial-track::-webkit-scrollbar { display: none; }

/* A common height rather than a common width: mixed portrait ratios then line
   up on one baseline without anything being cropped to get there. */
.editorial-item {
  flex: 0 0 auto;
  margin: 0;
  /* Sized against what is left of the viewport under the header and title,
     so the arrows stay in view on a laptop instead of falling below the fold;
     capped so it stops growing on a tall monitor. */
  height: clamp(300px, calc(100vh - 460px), 600px);
  /* Snap to the left edge, not the centre: it keeps the resting position in
     step with the arrows and the counter at both ends of the track. */
  scroll-snap-align: start;
  overflow: hidden;                                   /* holds the zoom in */
  box-shadow: 0 30px 56px -34px rgba(51, 36, 26, 0.55);
  transition: box-shadow 0.4s ease;
}
.editorial-item:hover { box-shadow: 0 38px 68px -34px rgba(51, 36, 26, 0.62); }

.editorial-photo {
  display: block;
  width: auto;
  height: 100%;
  transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.editorial-item:hover .editorial-photo { transform: scale(1.035); }

/* ---------- Carousel controls ---------- */
.carousel-controls {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: clamp(20px, 3vw, 30px);
}

.carousel-btn {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: none;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.25s ease, color 0.25s ease, opacity 0.25s ease;
}
.carousel-btn:hover:not(:disabled) { border-color: var(--ink); }
.carousel-btn:disabled { opacity: 0.28; cursor: default; }
.carousel-btn svg { width: 16px; height: 16px; }

/* Doubles as the scrollbar the track hides. */
.carousel-progress {
  flex: 1 1 auto;
  height: 1px;
  background: var(--line);
  position: relative;
}
.carousel-progress span {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--ink);
  transition: width 0.2s ease, transform 0.2s ease;
}


/* Quiet closing line — this work is enquired about, not bought off the page. */
.editorial-outro {
  margin-top: clamp(64px, 9vw, 104px);
  padding-top: clamp(28px, 4vw, 40px);
  border-top: 1px solid var(--line);
  text-align: center;
}
.editorial-outro a {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
  color: var(--ink-dim);
  border-bottom: 1px solid var(--line);
  padding-bottom: 3px;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.editorial-outro a:hover { color: var(--ink); border-color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .editorial-photo, .editorial-item:hover .editorial-photo {
    transition: none; transform: none;
  }
}

/* Shown while a category has no photos yet; delete it once tiles are added. */
.coming-soon {
  margin-top: 56px;
  padding: 64px 0;
  border-top: 1px solid var(--line);
  text-align: center;
  font-family: var(--font-subtitle);
  font-weight: 300;
  font-size: 0.8rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ---------- Contact ---------- */
.contact-block {
  margin-top: 44px;
  padding-top: 34px;
  border-top: 1px solid var(--line);
}
.contact-label {
  font-family: var(--font-subtitle);
  font-size: 0.72rem;
  font-weight: 300;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 6px;
}
.contact-label + * + .contact-label { margin-top: 30px; }

.contact-primary {
  display: inline-block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: clamp(1.15rem, 2.4vw, 1.5rem);
  line-height: 1.3;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  border-bottom: 2px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.contact-primary:hover { color: var(--accent-hover); border-bottom-color: currentColor; }

.contact-wa {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--ink);
  transition: color 0.15s ease, border-color 0.15s ease;
}
.contact-wa:hover { color: var(--accent-hover); border-color: var(--accent-hover); }

.contact-secondary {
  display: block;
  width: fit-content;
  margin-bottom: 6px;
  font-size: 1rem;
  color: var(--accent-hover);
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease;
}
.contact-secondary:hover { border-bottom-color: currentColor; }

/* ---------- Footer ---------- */
.site-footer {
  padding: 40px 24px;
  text-align: center;
  border-top: 1px solid var(--line);
}
.footer-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px 26px;
  margin-bottom: 22px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.82rem;
}
.footer-nav a { color: var(--ink-dim); transition: color 0.15s ease; }
.footer-nav a:hover,
.footer-nav a[aria-current="page"] { color: var(--ink); }

.footer-ig { display: inline-flex; color: var(--ink-dim); }
.footer-ig:hover { color: var(--accent); }

/* Build credit — deliberately quiet; present but never competing. */
.footer-credit {
  margin: 18px 0 0;
  font-size: 0.62rem;
  font-weight: 300;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
  opacity: 0.7;
}
.footer-credit a {
  color: inherit;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.footer-credit a:hover { color: var(--accent); border-bottom-color: currentColor; }

/* ---------- Reveal animation ---------- */
.reveal { opacity: 0; transition: opacity 0.6s ease; }
.reveal.in-view { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transition: none; }
  .editorial-track { scroll-behavior: auto; }
  .editorial-item, .editorial-item.reveal,
  .editorial-photo, .editorial-item.reveal .editorial-photo,
  .editorial-item:hover .editorial-photo {
    transform: none !important;
    transition: none !important;
  }
}

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  .two-col { grid-template-columns: 1fr; }
  /* Keeps the flyer from filling a phone screen before the book does. */
  .exhibition-flyer { max-width: 300px; margin-inline: auto; }
  /* Stacked under a centred image, ranged-left text reads as misaligned.
     The spec table keeps its label-left / value-right split: it is a table,
     and centring it would collapse the relationship between the two. */
  .exhibition-body,
  .col-text { text-align: center; }
  .cta-row { justify-content: center; gap: 12px 14px; }
  /* Tightened so "Get tickets" and "Purchase the book" both fit a 360px row. */
  .cta-row .icon-cta { gap: 10px; font-size: 0.82rem; }
  /* 44px is the minimum comfortable tap target; it still fits at 360px. */
  .cta-row .icon-cta-dot { width: 44px; height: 44px; }
  .cta-row .icon-cta-dot svg { width: 15px; height: 15px; }
  .col-text p { margin-inline: auto; }
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  /* Phones get the vertical stack instead: a carousel that has to be swiped
     hides most of the work behind a gesture people may not try. */
  .editorial-track {
    flex-direction: column;
    gap: clamp(40px, 8vw, 64px);
    overflow: visible;
    scroll-snap-type: none;
  }
  .editorial-item { width: 100%; height: auto; scroll-snap-align: none; }
  .editorial-photo { width: 100%; height: auto; }
  .carousel-controls { display: none; }

  /* Each photo rises into place and the image settles out of a slight zoom,
     so scrolling reveals the work rather than just scrolling past it. */
  .editorial-item.reveal {
    transform: translateY(32px);
    transition: opacity 0.7s ease, transform 0.85s cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  .editorial-item.reveal.in-view { transform: none; }
  .editorial-item.reveal .editorial-photo { transform: scale(1.07); }
  .editorial-item.reveal.in-view .editorial-photo {
    transform: none;
    transition: transform 1.2s cubic-bezier(0.22, 0.61, 0.36, 1);
  }
}

@media (max-width: 720px) {
  .main-nav {
    position: fixed;
    top: 0; right: 0;
    height: 100vh;
    width: min(78vw, 300px);
    background: var(--bg-alt);
    border-left: 1px solid var(--line);
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 24px;
    padding: 40px;
    transform: translateX(100%);
    transition: transform 0.3s ease;
  }
  .main-nav.open { transform: translateX(0); }
  .nav-toggle { display: flex; }
  .nav-toggle.open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .nav-toggle.open span:nth-child(2) { opacity: 0; }
  .nav-toggle.open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
}

@media (max-width: 480px) {
  .btn { text-align: center; }
}
