/* =========================================================
   JULIAN ALFAENGER — PHOTOGRAPHY PORTFOLIO
   Stripped chrome, dark hero, editorial content
   ========================================================= */

:root {
  --paper:     #F1EEE7;
  --paper-2:   #E8E4DA;
  /* tinted-alpha paper — replaces rgba(255,255,255,...) everywhere type
     sits on photo backgrounds. Pure-white-with-alpha reads flat on
     dark imagery; warm-tinted alpha keeps the typography of a piece
     with the paper palette and the Portra-graded hero. */
  --paper-92:  rgba(241, 238, 231, .92);
  --paper-68:  rgba(241, 238, 231, .68);
  --paper-42:  rgba(241, 238, 231, .42);

  --ink:       #111111;
  --ink-70:    rgba(17,17,17,.70);
  --ink-45:    rgba(17,17,17,.45);
  --ink-20:    rgba(17,17,17,.20);
  --ink-10:    rgba(17,17,17,.10);
  --accent:    #A14726;

  --serif: "Instrument Serif", "Times New Roman", serif;
  --sans:  "Bricolage Grotesque", ui-sans-serif, system-ui, -apple-system, sans-serif;

  --pad-x:   clamp(24px, 5vw, 80px);
  --pad-y:   clamp(80px, 12vw, 180px);
  --nav-h:   64px;

  --ease:    cubic-bezier(.2,.8,.2,1);
  --ease-slow: cubic-bezier(.16,1,.3,1);
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
body { overflow-x: clip; background: var(--paper); }
img, svg, video { display: block; max-width: 100%; }
img, video { -webkit-user-drag: none; user-select: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ol, ul { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, h4, p { margin: 0; }

::selection { background: var(--ink); color: var(--paper); }

@media (hover: hover) and (pointer: fine) {
  html, body, a, button { cursor: none; }
}

/* ---------- WEBGL GRAIN CANVAS ---------- */
.gl {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 9000;
  opacity: .08;
  mix-blend-mode: overlay;
}

/* ---------- CURSOR ---------- */
.cursor { position: fixed; inset: 0; pointer-events: none; z-index: 9999; display: none; }
@media (hover: hover) and (pointer: fine) { .cursor { display: block; } }
.cursor__dot, .cursor__ring {
  position: absolute; top: 0; left: 0;
  transform: translate3d(-100px, -100px, 0);
  border-radius: 999px;
  will-change: transform;
}
.cursor__dot  { width: 5px; height: 5px; background: var(--ink); margin: -2.5px 0 0 -2.5px; }
.cursor__ring {
  width: 30px; height: 30px;
  border: 1px solid var(--ink);
  margin: -15px 0 0 -15px;
  transition: width .35s var(--ease), height .35s var(--ease),
              margin .35s var(--ease), border-color .3s var(--ease);
  mix-blend-mode: difference;
}
.cursor.is-hover .cursor__ring {
  width: 56px; height: 56px; margin: -28px 0 0 -28px;
}
.cursor.is-dark .cursor__dot  { background: var(--paper); }
.cursor.is-dark .cursor__ring { border-color: var(--paper); }

/* Lightbox-open: force paper-color cursor regardless of scroll-based is-dark
   state. Covers all 4 lightbox flavors (.lb.is-open for arch/nature/urban/art,
   body.is-lb-open as belt-and-braces for the pages that set it). */
body.is-lb-open .cursor__dot,
body:has(.lb.is-open) .cursor__dot {
  background: var(--paper) !important;
}
body.is-lb-open .cursor__ring,
body:has(.lb.is-open) .cursor__ring {
  border-color: var(--paper) !important;
}

/* ---------- LOADER — curtain-style, real progress ---------- */
.loader {
  position: fixed; inset: 0; z-index: 9500;
  background: #000;
  color: #F1EEE7;
  pointer-events: none;
  will-change: transform;
  /* curtain-up exit: translate whole panel off-screen */
  transform: translate3d(0, 0, 0);
  transition: transform 1.05s cubic-bezier(0.76, 0, 0.24, 1);
}
.loader.is-done { transform: translate3d(0, -101%, 0); }

.loader__grid {
  position: absolute; inset: 0;
  padding: clamp(20px, 3.2vw, 44px);
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  grid-template-columns: 1fr 1fr;
  column-gap: 24px;
  row-gap: clamp(18px, 3vh, 28px);
}

/* corners — tiny all-caps labels */
.loader__tl, .loader__tr, .loader__bl, .loader__br {
  font-family: 'Bricolage Grotesque', sans-serif;
  font-size: 10.5px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.55;
  line-height: 1;
}
.loader__tl { grid-row: 1; grid-column: 1; text-align: left; display: inline-flex; align-items: center; gap: 10px; }
.loader__tr { grid-row: 1; grid-column: 2; text-align: right; }
.loader__bl { grid-row: 4; grid-column: 1; text-align: left; }
.loader__br { grid-row: 4; grid-column: 2; text-align: right; font-variant-numeric: tabular-nums; letter-spacing: 0.14em; }

/* pulsing dot next to brand */
.loader__tl .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: #F1EEE7; display: inline-block;
  animation: loader-pulse 1.6s ease-in-out infinite;
}
@keyframes loader-pulse {
  0%, 100% { opacity: 0.3; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.25); }
}

/* center stage — massive percent counter + status */
.loader__center {
  grid-row: 2; grid-column: 1 / -1;
  display: flex; flex-direction: column;
  justify-content: center; align-items: center;
  gap: clamp(14px, 2vh, 22px);
}
.loader__num-wrap {
  position: relative;
  display: inline-flex;
  align-items: flex-end;
  line-height: 0.82;
}
.loader__num {
  font-family: 'Instrument Serif', serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(160px, 26vw, 340px);
  letter-spacing: -0.045em;
  font-variant-numeric: tabular-nums;
  color: #F1EEE7;
  display: inline-block;
}
.loader__num-suffix {
  font-family: 'Instrument Serif', serif;
  font-style: italic;
  font-size: clamp(32px, 5.5vw, 64px);
  opacity: 0.4;
  margin-left: 0.15em;
  margin-bottom: 0.12em;
  letter-spacing: -0.02em;
}
.loader__status {
  font-family: 'Instrument Serif', serif;
  font-style: italic;
  font-size: clamp(15px, 1.5vw, 19px);
  opacity: 0.45;
  letter-spacing: 0.01em;
}

/* hairline progress bar */
.loader__bar {
  grid-row: 3; grid-column: 1 / -1;
  height: 1px;
  background: rgba(241, 238, 231, 0.12);
  position: relative;
  overflow: hidden;
}
.loader__bar-fill {
  position: absolute; inset: 0 auto 0 0;
  width: 100%;
  background: #F1EEE7;
  transform-origin: 0 50%;
  transform: scaleX(0);
  will-change: transform;
}

/* reduced motion — no curtain, just a clean fade */
@media (prefers-reduced-motion: reduce) {
  .loader { transition: opacity .6s ease; }
  .loader.is-done { transform: none; opacity: 0; }
  .loader__tl .dot { animation: none; opacity: 0.8; }
}

/* ---------- NAV ----------
   Stays hidden during the preloader. `body.is-ready` is added the
   instant the loader starts its curtain exit; nav fades + slides in
   while the curtain is lifting, so by the time the hero is revealed
   the nav is already fully there. */
.nav {
  position: fixed; inset: 0 0 auto 0;
  height: var(--nav-h);
  padding: 0 var(--pad-x);
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  z-index: 8000;
  color: var(--ink);
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition:
    opacity   .6s cubic-bezier(0.76, 0, 0.24, 1) .25s,
    transform .7s cubic-bezier(0.22, 1, 0.36, 1) .25s,
    color       .4s var(--ease),
    background-color .4s var(--ease);
}
body.is-ready .nav {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.nav.is-dark { color: var(--paper); }
.nav.is-scrolled {
  background: color-mix(in oklab, var(--paper) 78%, transparent);
  backdrop-filter: blur(14px) saturate(1.1);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  border-bottom: 1px solid var(--ink-10);
}
.nav.is-dark.is-scrolled {
  background: color-mix(in oklab, #000 45%, transparent);
  border-bottom-color: rgba(255,255,255,.12);
}
.nav__brand {
  display: inline-flex; align-items: center;
  text-decoration: none;
  color: inherit;
  line-height: 1;
  /* let inner span handle styling */
}
.nav__logo {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  line-height: 1;
  /* subtle lift of italic serif to sit visually centered with tag */
}
.nav__logo-mark {
  position: relative;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: 22px;
  letter-spacing: -0.012em;
  line-height: 1;
  padding-bottom: 2px;   /* room for the underline sweep */
}
.nav__logo-mark::after {
  /* hover underline — agency-grade 1px sweep */
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .55s cubic-bezier(0.76, 0, 0.24, 1);
}
.nav__brand:hover .nav__logo-mark::after {
  transform: scaleX(1);
}
.nav__logo-dot {
  width: 3px; height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.45;
  transition: opacity .4s var(--ease), transform .4s var(--ease);
  flex-shrink: 0;
}
.nav__brand:hover .nav__logo-dot {
  opacity: 1;
  transform: scale(1.25);
}
.nav__logo-tag {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  opacity: 0.7;
  /* small optical lift to align x-height with the serif cap-line */
  padding-top: 1px;
  transition: opacity .4s var(--ease);
}
.nav__brand:hover .nav__logo-tag {
  opacity: 1;
}

/* Mobile: shorten to serif wordmark only */
@media (max-width: 560px) {
  .nav__logo-dot,
  .nav__logo-tag { display: none; }
  .nav__logo-mark { font-size: 20px; }
}
.nav__links {
  display: flex; gap: clamp(18px, 2.4vw, 36px);
  font-size: 12.5px; letter-spacing: .02em;
}
.nav__links a {
  position: relative; padding: 8px 2px;
}
.nav__links a::after {
  content: ""; position: absolute; inset: auto 0 4px 0;
  height: 1px; background: currentColor; transform: scaleX(0);
  transform-origin: left; transition: transform .4s var(--ease);
}
.nav__links a:hover::after,
.nav__links a.is-active::after { transform: scaleX(1); }
/* Secondary link (e.g. Impressum) — separated by a fine rule, dimmed */
.nav__link-alt {
  padding-left: clamp(10px, 1.2vw, 18px) !important;
  margin-left: clamp(4px, .8vw, 10px);
  border-left: 1px solid currentColor;
  opacity: .55;
  transition: opacity .3s var(--ease);
}
.nav__link-alt:hover { opacity: 1; }
.nav__meta {
  justify-self: end;
  font-size: 10.5px; letter-spacing: .28em; text-transform: uppercase;
  opacity: .55;
}

@media (max-width: 860px) {
  .nav__links { gap: 14px; font-size: 12px; }
  .nav__meta { font-size: 10px; }
}
@media (max-width: 560px) {
  .nav { grid-template-columns: 1fr auto; }
  .nav__links { display: none; }
  .nav__meta { display: none; }
}

/* ==========================================================
   MOBILE BURGER + FULL-SCREEN MENU
   ========================================================== */
.nav__burger {
  display: none;
  justify-self: end;
  width: 44px; height: 44px;
  padding: 0;
  background: transparent;
  border: 0;
  color: inherit;
  cursor: pointer;
  position: relative;
}
.nav__burger span {
  position: absolute;
  left: 10px; right: 10px;
  height: 1.5px;
  background: currentColor;
  transition: transform .5s cubic-bezier(0.76, 0, 0.24, 1), opacity .3s;
}
.nav__burger span:nth-child(1) { top: 17px; }
.nav__burger span:nth-child(2) { top: 25px; }
/* open state */
body.is-menu-open .nav__burger span:nth-child(1) { transform: translateY(4px) rotate(45deg); }
body.is-menu-open .nav__burger span:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }

@media (max-width: 560px) {
  .nav__burger { display: inline-flex; align-items: center; justify-content: center; }
}

/* full-screen overlay menu */
.mobile-menu {
  position: fixed; inset: 0;
  z-index: 7900;
  background: #0a0a0a;
  color: var(--paper);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: calc(var(--nav-h) + 8px) clamp(28px, 7vw, 56px) clamp(28px, 5vh, 48px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s cubic-bezier(0.76, 0, 0.24, 1);
}
body.is-menu-open .mobile-menu {
  opacity: 1;
  pointer-events: auto;
}
.mobile-menu[aria-hidden="false"] { /* a11y only */ }

.mobile-menu__close {
  position: absolute; top: 12px; right: clamp(16px, 5vw, 24px);
  width: 44px; height: 44px;
  background: transparent; border: 0;
  cursor: pointer;
  opacity: 0;
}

.mobile-menu__links {
  display: grid;
  align-content: center;
  gap: clamp(14px, 3.2vh, 28px);
}
.mobile-menu__links a {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(44px, 11vw, 84px);
  line-height: .95;
  letter-spacing: -.02em;
  color: var(--paper);
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 14px;
  text-decoration: none;
  /* entrance: offset + fade, staggered via JS/body class */
  transform: translateY(24px);
  opacity: 0;
  transition: transform .7s cubic-bezier(0.22, 1, 0.36, 1), opacity .7s;
}
.mobile-menu__links a em {
  font-style: italic;
  font-size: 12px;
  letter-spacing: .22em;
  font-family: var(--sans);
  font-weight: 500;
  color: rgba(241,238,231,.4);
  align-self: flex-start;
  padding-top: 8px;
  text-transform: uppercase;
}
body.is-menu-open .mobile-menu__links a { transform: translateY(0); opacity: 1; }
body.is-menu-open .mobile-menu__links a:nth-child(1) { transition-delay: .12s; }
body.is-menu-open .mobile-menu__links a:nth-child(2) { transition-delay: .18s; }
body.is-menu-open .mobile-menu__links a:nth-child(3) { transition-delay: .24s; }
body.is-menu-open .mobile-menu__links a:nth-child(4) { transition-delay: .30s; }
body.is-menu-open .mobile-menu__links a:nth-child(5) { transition-delay: .36s; }
/* Secondary alt link (Impressum) — smaller, dimmed, separated by top hairline */
.mobile-menu__alt {
  font-size: clamp(20px, 4.5vw, 30px) !important;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid rgba(241,238,231,.14);
  opacity: .65;
}
body.is-menu-open .mobile-menu__alt { opacity: .65; }
.mobile-menu__alt:hover { opacity: 1; }

.mobile-menu__foot {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 10.5px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(241,238,231,.55);
  padding-top: 24px;
  border-top: 1px solid rgba(241,238,231,.14);
}
.mobile-menu__foot a {
  font-family: var(--serif);
  font-style: italic;
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--paper);
}

body.is-menu-open { overflow: hidden; }

/* ==============================================================
   HERO
   ============================================================== */
.hero {
  position: relative;
  min-height: 100svh;
  padding: var(--nav-h) var(--pad-x) 0;
  display: grid; place-items: stretch;
  overflow: hidden;
  background: #0a0a0a;
  color: var(--paper);
}
.hero__bg-clip {
  position: absolute; inset: 0;
  overflow: hidden;
  clip-path: inset(48% 0 48% 0);
  will-change: clip-path;
}
.hero.is-ready .hero__bg-clip {
  animation: apertureOpen 1.6s .2s var(--ease-slow) forwards;
}
@keyframes apertureOpen { to { clip-path: inset(0 0 0 0); } }
.hero__bg {
  position: absolute; inset: -4%;
  will-change: transform;
}
/* WebGL canvas — the actual visible hero image */
.hero__gl {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
  transform: scale(1.12);
  animation: bgSettle 4s .2s var(--ease-slow) forwards;
  will-change: transform;
}
/* Video kept in DOM as WebGL texture source — invisible but decoded */
.hero__src {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
}
@keyframes bgSettle {
  to { transform: scale(1.04); }
}
.hero__overlay {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(0,0,0,.45) 0%, rgba(0,0,0,.15) 30%, rgba(0,0,0,.35) 60%, rgba(0,0,0,.8) 100%);
  pointer-events: none;
}
.hero__vignette {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, transparent 35%, rgba(0,0,0,.55) 100%);
  pointer-events: none;
}

.hero__stage {
  position: relative;
  align-self: center;
  max-width: 1600px; width: 100%;
  margin-inline: auto;
  /* NB: no z-index — it would create an isolating stacking context
     and break mix-blend-mode: difference on the hero title */
}
.hero__title {
  font-family: var(--sans);
  font-weight: 500;
  font-variation-settings: "wght" 500, "wdth" var(--wdth, 100), "opsz" 96;
  /* clamp lower bound tuned so "Photography" (11 char) fits 375px mobile */
  font-size: clamp(44px, 13.2vw, 260px);
  line-height: .86;
  letter-spacing: -.045em;
  color: #fff;                       /* pure white matters for difference blend */
  margin: 0;
  text-transform: uppercase;
  /* the killer move: name reads as inverse of whatever pixel sits behind */
  mix-blend-mode: difference;
}
/* mobile: tighter tracking + narrower width axis so the longest word fits */
@media (max-width: 480px) {
  .hero__title {
    letter-spacing: -.055em;
    font-variation-settings: "wght" 500, "wdth" 85, "opsz" 96;
  }
}
.hero__title .line { display: block; overflow: hidden; padding-block: .02em; }
.hero__title .word { display: inline-block; white-space: nowrap; }
.hero__title .char {
  display: inline-block;
  will-change: transform, font-variation-settings;
  /* per-char weight (set on mousemove), width inherited from title (scroll-scrubbed) */
  font-variation-settings: "wght" var(--w, 500), "wdth" var(--wdth, 100), "opsz" 96;
  transition: font-variation-settings .4s cubic-bezier(.2,.8,.2,1);
}

.hero__scroll {
  position: absolute; bottom: clamp(24px, 3vw, 40px); left: var(--pad-x);
  font-size: 10.5px; letter-spacing: .28em; text-transform: uppercase;
  color: rgba(255,255,255,.7);
  opacity: 0; animation: fadeIn .8s 2.2s var(--ease) forwards;
  z-index: 3;
}
@keyframes fadeIn { to { opacity: 1; } }

/* ==============================================================
   REVEAL
   ============================================================== */
.reveal {
  padding: clamp(40px, 8vw, 100px) var(--pad-x) clamp(40px, 6vw, 80px);
  background: var(--paper);
}
.reveal__frame {
  position: relative; margin: 0;
  aspect-ratio: 16 / 9; width: 100%;
  overflow: hidden;
  background: #111;
  clip-path: inset(45% 0 45% 0);
  transition: clip-path 1.4s var(--ease-slow);
}
.reveal__frame.is-in { clip-path: inset(0 0 0 0); }
.reveal__frame img {
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(1.12);
  transition: transform 8s linear;
}
.reveal__frame.is-in img { transform: scale(1); }
.reveal__cap {
  position: absolute; left: 20px; bottom: 18px;
  color: rgba(255,255,255,.82);
  font-size: 10.5px; letter-spacing: .28em; text-transform: uppercase;
  opacity: 0; transition: opacity .6s 1.2s var(--ease);
}
.reveal__frame.is-in .reveal__cap { opacity: 1; }

/* ==============================================================
   MANIFESTO (minimal, single sentence)
   ============================================================== */
.manifesto {
  padding: var(--pad-y) var(--pad-x);
  max-width: 1600px; margin-inline: auto;
}
.manifesto__text {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(44px, 7vw, 120px);
  line-height: 1.04;
  letter-spacing: -.015em;
  max-width: 18ch;
}
.reveal-word {
  display: inline-block;
  opacity: .1;
  transition: opacity .6s var(--ease);
  margin-right: .18em;
}
.reveal-word.is-lit { opacity: 1; }

/* ==============================================================
   PORTFOLIO — horizontal magazine rail
   Four chapters on a native horizontal scroll with snap-align.
   Hover (desktop) reveals editorial overlay + saturates the active
   panel while neighbours desaturate + darken. Mobile shows overlay
   always and relies on snap-scroll for focus.
   ============================================================== */
.folio {
  padding: var(--pad-y) 0;
  background: var(--paper);
  /* no horizontal padding: the rail itself handles its own gutters so
     it can bleed edge-to-edge and still snap correctly */
}
.folio__head {
  max-width: 1800px; margin: 0 auto clamp(40px, 5vw, 72px);
  padding: 0 var(--pad-x);
  display: grid;
  gap: clamp(16px, 1.8vw, 28px);
}
.folio__eyebrow {
  font-family: var(--sans);
  font-size: 10.5px; font-weight: 500;
  letter-spacing: .28em; text-transform: uppercase;
  color: var(--ink-45);
  display: inline-flex; align-items: center; gap: 10px;
}
.folio__eyebrow span {
  display: inline-block;
  animation: folio-eyebrow-arrow 2.4s cubic-bezier(.76,0,.24,1) infinite;
}
@keyframes folio-eyebrow-arrow {
  0%,60%,100% { transform: translateX(0); opacity: .7; }
  30%         { transform: translateX(4px); opacity: 1; }
}
.folio__title {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(64px, 11vw, 200px);
  line-height: .9; letter-spacing: -.02em;
  margin: 0;
}
.folio__title em { font-style: italic; color: var(--accent); }
.folio__title .line { display: block; overflow: hidden; padding-block: .04em; }
.folio__title .word {
  display: inline-block; transform: translate3d(0, 110%, 0);
  transition: transform 1s var(--ease-slow);
}
.folio__title.is-in .word { transform: translate3d(0, 0, 0); }
.folio__title.is-in .line:nth-child(2) .word { transition-delay: .12s; }

/* ---- Rail container ----------------------------------------------
   On desktop: the rail is pinned to 100svh and GSAP translates the
   inner track horizontally while the user scrolls vertically. Panels
   snap to viewport-center because track padding is exactly
   (100vw - chapter_width) / 2 on each side.
   On mobile/touch/reduced-motion: falls back to native horizontal
   scroll with scroll-snap (see media queries below). */
.folio__rail {
  position: relative;
  height: 100svh;
  max-width: 100%;
  overflow: hidden;   /* clip any overshoot from the track during scrub */
}

.folio__viewport {
  position: relative;
  width: 100%; height: 100%;
  overflow: hidden;
}

.folio__track {
  display: flex;
  gap: clamp(14px, 1.8vw, 30px);
  /* side padding centers the first / last panel in the viewport:
     (100vw − chapter_width) / 2. Must match the chapter width clamp
     below; CSS calc supports clamp() inside, so this stays in sync. */
  padding-inline: calc((100vw - clamp(360px, 54vw, 820px)) / 2);
  height: 100%;
  align-items: center;
  width: max-content;
  will-change: transform;
  backface-visibility: hidden;
}

/* ---- Chapter panel ----------------------------------------------
   Sized to fill the pinned 100svh rail more generously. Height 86svh
   leaves ~14svh for the progress strip + a modest bottom buffer.
   Width bumped slightly so panels feel weighty but neighbour peeks
   are preserved on all desktop viewports.

   SCOPED to `.folio__track .chapter` to avoid a class-name clash
   with `<span class="chapter">` inside .n-nav__counter / .u-nav__counter
   on gallery pages (which share this stylesheet). Without this scope,
   the mobile width/height clamps below would blow the nav span up to
   ~364×619px and displace the whole nav layout. */
.folio__track .chapter {
  position: relative;
  flex: 0 0 auto;
  width: clamp(360px, 54vw, 820px);
  height: clamp(580px, 86svh, 960px);
  /* default: visible. JS opts-in to entrance animation by adding
     .is-rail-pending to .folio. If JS never runs, chapters just
     appear — no blank rail. */
}

/* Entrance stagger — pending class added by JS the instant the rail
   initialises, animation class added when the section crosses viewport. */
.folio.is-rail-pending .chapter {
  opacity: 0;
  transform: translateY(36px);
  transition:
    opacity 1s var(--ease-slow),
    transform 1s var(--ease-slow);
}
.folio.is-rail-in .chapter { opacity: 1; transform: translateY(0); }
.folio.is-rail-in .chapter:nth-child(1) { transition-delay: .00s; }
.folio.is-rail-in .chapter:nth-child(2) { transition-delay: .08s; }
.folio.is-rail-in .chapter:nth-child(3) { transition-delay: .16s; }
.folio.is-rail-in .chapter:nth-child(4) { transition-delay: .24s; }

.chapter__inner {
  position: absolute; inset: 0;
  display: block;
  overflow: hidden;
  color: #fff;
  background: #0a0a0a;
  isolation: isolate;
  /* focus ring — agency grade, only visible via keyboard */
  outline: 0;
}
.chapter__inner:focus-visible {
  box-shadow: inset 0 0 0 2px var(--paper), inset 0 0 0 4px var(--ink);
}

.chapter__bg {
  position: absolute; inset: -6% -4%;
  background-image: var(--img);
  background-size: cover;
  background-position: center;
  transform: scale(1);
  /* Default = non-active panel: clearly desaturated + dimmed so the
     active panel reads as the single visual focus. Active-state
     overrides below bring it back to full colour. Transition is
     tight (.45s) so the active-swap tracks the snap instead of
     lagging behind it. */
  filter: grayscale(.6) brightness(.6) contrast(1.02);
  will-change: transform, filter;
  transition:
    transform .75s cubic-bezier(.2,.8,.2,1),
    filter .45s var(--ease);
}

.chapter__overlay {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(0,0,0,.28) 0%,
      rgba(0,0,0,0)   22%,
      rgba(0,0,0,0)   48%,
      rgba(0,0,0,.55) 82%,
      rgba(0,0,0,.82) 100%);
  pointer-events: none;
  transition: background .6s var(--ease);
}

/* ---- TYPOGRAPHY SYSTEM — maximum
   Three sizes, dramatic ratio (1 : 1.6 : 13): micro · body · display.
   Display is VARIABLE SANS not serif italic (2025 SOTY direction).
   Instrument Serif italic is reserved for the single body-sized
   description line. Numerals set tabular + slashed-zero. Caps
   letterspacing is .08em (tight-modern, not the .28em cliché).
   Colors use warm-tinted paper-alpha tokens, never pure-white-alpha.
   ============================================================== */

/* ---- Head: index + kind label (top-left) ----------------------- */
.chapter__head {
  position: absolute; top: 0; left: 0; right: 0;
  padding: clamp(20px, 2.2vw, 32px) clamp(22px, 2.4vw, 34px);
  display: flex; justify-content: flex-start; align-items: flex-start;
  z-index: 2;
  pointer-events: none;
}
.chapter__num {
  font-family: var(--sans);
  font-size: 11.5px; font-weight: 500;
  font-variant-numeric: tabular-nums slashed-zero;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--paper-68);
  display: inline-flex; align-items: center;
  gap: 10px;
  line-height: 1;
}
.chapter__num-dash {
  display: inline-block;
  opacity: .55;
  /* em-dash separator — more editorial than middle-dot here */
}
.chapter__num-kind {
  /* "Chapter" label — slightly dimmer than the number, signals meta */
  opacity: .7;
}
/* ---- Body: meta · title · description · foot --------------------- */
.chapter__body {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: clamp(24px, 2.8vw, 40px) clamp(24px, 2.8vw, 40px) clamp(28px, 3.2vw, 46px);
  display: grid;
  gap: clamp(12px, 1.1vw, 18px);
  z-index: 2;
}

/* EXIF-style metadata line — locations · frame count · year range.
   Middle-dot separator (U+00B7). Tight caps spacing, tabular nums
   for the year range. Hidden by default, revealed on hover. */
.chapter__meta {
  font-family: var(--sans);
  font-size: 11px; font-weight: 500;
  font-variant-numeric: tabular-nums slashed-zero;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--paper-68);
  margin: 0 0 clamp(2px, .3vw, 6px);
  opacity: 0; transform: translateY(8px);
  transition:
    opacity .55s var(--ease),
    transform .6s cubic-bezier(.22,1,.36,1);
}

/* DISPLAY — the category name. Instrument Serif italic, sentence
   case. Editorial-photographer register (Pentagram / Pushinsky
   / Joanna Kustra). Restrained, warm, classical. Sized to fit
   the longest title ("Architecture") on a single line at all
   supported desktop viewports. */
.chapter__title {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(60px, 8.5vw, 135px);
  line-height: .94;
  letter-spacing: -.015em;
  text-transform: none;
  color: var(--paper-92);
  margin: 0;
  /* title always visible — hover doesn't un-reveal it like the rest */
}

/* Body description — Bricolage sans, clean grounded voice, serves
   as the practical counterpoint to the voiced italic title. Uses
   <em> to elevate a single phrase into Instrument Serif italic
   as an accent within the paragraph — classical editorial move. */
.chapter__desc {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-variation-settings: "wght" 400, "wdth" 100, "opsz" 32;
  font-size: clamp(16px, 1.3vw, 21px);
  line-height: 1.5;
  letter-spacing: -.005em;
  color: var(--paper-92);
  max-width: 36ch;
  margin: 0;
  opacity: 0; transform: translateY(10px);
  transition:
    opacity .6s var(--ease),
    transform .7s cubic-bezier(.22,1,.36,1);
}
.chapter__desc em {
  /* italic serif accent within a sans paragraph */
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  color: var(--paper-92);
}


/* Foot row — CTA on the left, © ownership mark on the right */
.chapter__foot {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: clamp(6px, 1vw, 14px);
  gap: 18px;
}

/* CTA — arrow on LEFT (pulling you in, not trailing). Underline
   sweeps under the text on hover. */
.chapter__cta {
  display: inline-flex; align-items: baseline;
  gap: 12px;
  padding-bottom: 5px;
  font-family: var(--sans);
  font-size: 11px; font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--paper-92);
  position: relative;
  width: fit-content;
  opacity: 0; transform: translateY(10px);
  transition:
    opacity .6s var(--ease),
    transform .7s cubic-bezier(.22,1,.36,1);
}
.chapter__cta::after {
  content: "";
  position: absolute; left: 24px; right: 0; bottom: 0;
  /* underline only under the text, not the arrow */
  height: 1px; background: var(--paper-92);
  transform: scaleX(0); transform-origin: left;
  transition: transform .55s cubic-bezier(.76,0,.24,1);
}
.chapter__cta-arrow {
  display: inline-block;
  transition: transform .5s cubic-bezier(.76,0,.24,1);
  font-size: 14px;
  line-height: 1;
  color: var(--paper-92);
  /* nudge up a hair so arrow sits on x-height baseline */
  transform: translateY(1px);
}

/* Ownership mark — © glyph as permanent sign-off, always visible.
   naughtyduk-style. Dim enough to read as a seal rather than content. */
.chapter__mark {
  font-family: var(--sans);
  font-size: 11px; font-weight: 500;
  letter-spacing: .02em;
  color: var(--paper-42);
  line-height: 1;
  user-select: none;
}

/* ---- ACTIVE STATE — deterministic, tied to scroll position -----
   All panel visual state (bg colour/scale, overlay gradient, text
   reveals, CTA underline) is driven by the .is-active class — set
   by script.js onUpdate based on which panel is centered in the
   rail. Not by :hover.

   Why: during rail scroll the user's cursor stays roughly at the
   viewport centre while panels slide UNDER it. A :hover-based
   system would fire mouseenter/mouseleave on every panel that
   passes under the cursor — each one briefly triggering a scale,
   colour, text-fade, and neighbour-desat cascade. That's the
   "inputless movement" the user sees. Decoupling state from
   cursor position eliminates the cascade entirely.

   Keyboard focus: `:has(.chapter__inner:focus-visible)` mirrors
   the active state so tab-navigation reveals content for a11y
   without needing a separate JS class.
   ================================================================ */

/* Active panel: full colour, slight scale, overlay gradient lighter */
.chapter.is-active .chapter__bg,
.chapter:has(.chapter__inner:focus-visible) .chapter__bg {
  filter: grayscale(0) brightness(1) contrast(1.04);
  transform: scale(1.02);
}
.chapter.is-active .chapter__overlay,
.chapter:has(.chapter__inner:focus-visible) .chapter__overlay {
  background:
    linear-gradient(180deg,
      rgba(0,0,0,.18) 0%,
      rgba(0,0,0,0)   20%,
      rgba(0,0,0,.10) 45%,
      rgba(0,0,0,.68) 82%,
      rgba(0,0,0,.92) 100%);
}

/* Active panel: reveal meta / desc / cta with a tiny stagger so the
   order reads as a single phrase settling in, not four elements
   popping together. Delays are short because they ride on top of
   the snap — the user sees snap + reveal as one unified motion. */
.chapter.is-active .chapter__meta,
.chapter:has(.chapter__inner:focus-visible) .chapter__meta {
  opacity: 1; transform: none;
  transition-delay: .02s;
}
.chapter.is-active .chapter__desc,
.chapter:has(.chapter__inner:focus-visible) .chapter__desc {
  opacity: 1; transform: none;
  transition-delay: .08s;
}
.chapter.is-active .chapter__cta,
.chapter:has(.chapter__inner:focus-visible) .chapter__cta {
  opacity: 1; transform: none;
  transition-delay: .14s;
}
.chapter.is-active .chapter__cta::after,
.chapter:has(.chapter__inner:focus-visible) .chapter__cta::after {
  transform: scaleX(1);
  transition-delay: .22s;
}

/* Overlay + default gradient for non-active panels. Slightly deeper
   than the active gradient to push them back in the stack. */
.chapter__overlay {
  transition: background .4s var(--ease);
}

/* Global-overlay default (non-active) — keep it defined after the
   active override so the cascade resolves correctly.  */
.chapter:not(.is-active):not(:has(.chapter__inner:focus-visible)) .chapter__overlay {
  background:
    linear-gradient(180deg,
      rgba(0,0,0,.42) 0%,
      rgba(0,0,0,.25) 45%,
      rgba(0,0,0,.58) 100%);
}

/* ---- Mobile panel sizing ONLY ------------------------------------
   Pin model is unified across desktop and mobile — same pin + scrub
   behaviour, just with smaller panel dimensions that fit narrower
   phone viewports. Everything else (rail 100svh, viewport overflow
   hidden, track transform via GSAP) inherits from the base rules
   above. No native horizontal scroll on mobile — everything is
   driven by the pin, with a horizontal touch handler (in script.js)
   mapping finger dx to scrollY delta so horizontal swipes also
   advance the rail. No snap anywhere — stufenlos continuous. */
@media (max-width: 780px) {
  .folio__track {
    padding-inline: calc((100vw - min(82vw, 540px)) / 2);
  }
  .folio__track .chapter {
    width: min(82vw, 540px);
    height: clamp(480px, 78svh, 720px);
  }
  .chapter__title {
    /* scales down so "Architecture" fits on a single line on narrow
       phones */
    font-size: clamp(44px, 11vw, 86px);
  }
  .chapter__head,
  .chapter__body { padding-inline: 22px; }
}
@media (max-width: 480px) {
  .folio__track {
    padding-inline: calc((100vw - 88vw) / 2);
  }
  .folio__track .chapter {
    width: 88vw;
  }
  .chapter__body { padding-bottom: 26px; }
}

/* ---- Reduced motion: no pin, no horizontal scrub ----------------
   Panels stack vertically with a subtle aspect-ratio so each is
   readable at a glance. Preserves content + hierarchy without
   forcing scroll-hijack on users who opt out. */
@media (prefers-reduced-motion: reduce) {
  .folio__rail { height: auto; overflow: visible; }
  .folio__viewport { overflow: visible; height: auto; }
  .folio__track {
    flex-direction: column;
    width: auto;
    padding: 0 var(--pad-x);
    gap: 20px;
    height: auto;
    transform: none !important;
  }
  .folio__track .chapter {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 10;
  }
  .folio__progress { position: static !important; }
}

/* ---- Progress strip ---------------------------------------------
   On desktop the progress strip is absolutely positioned inside the
   pinned rail, so it remains visible at the bottom of the viewport
   throughout the horizontal scrub. On mobile / reduced-motion it
   drops back into static flow below the rail. */
.folio__progress {
  position: absolute;
  left: 0; right: 0;
  bottom: clamp(24px, 3.5vh, 44px);
  max-width: 1800px; margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(16px, 2vw, 32px);
  font-family: var(--sans);
  font-size: 10.5px; font-weight: 500;
  letter-spacing: .28em; text-transform: uppercase;
  color: var(--ink-45);
  z-index: 2;
  pointer-events: none;
}
.folio__progress-count { font-variant-numeric: tabular-nums; }
.folio__progress-count #folio-active { color: var(--ink); }
.folio__progress-sep { padding: 0 6px; opacity: .4; }
.folio__progress-track {
  position: relative;
  height: 1px;
  background: var(--ink-10);
  display: block;
}
.folio__progress-fill {
  position: absolute; inset: 0 auto 0 0;
  width: 100%;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .4s cubic-bezier(.2,.8,.2,1);
}
.folio__progress-label {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: 14px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  min-width: 9ch; text-align: right;
  transition: opacity .3s var(--ease);
}
@media (max-width: 560px) {
  .folio__progress {
    grid-template-columns: auto 1fr;
    row-gap: 8px;
  }
  .folio__progress-label { grid-column: 1 / -1; text-align: left; }
}

/* ---- Reduced motion — panel-level animation overrides -----------
   (Layout overrides live in the main reduced-motion block above.) */
@media (prefers-reduced-motion: reduce) {
  .folio__track .chapter { opacity: 1; transform: none; transition: none; }
  .chapter__bg { transition: none; }
  .folio__eyebrow span { animation: none; }
}

/* ==============================================================
   ABOUT
   ============================================================== */
.about {
  padding: var(--pad-y) var(--pad-x);
  display: grid;
  grid-template-columns: minmax(280px, 1fr) 1.4fr;
  gap: clamp(40px, 6vw, 100px);
  max-width: 1800px; margin-inline: auto;
  align-items: start;
}
.about__portrait {
  margin: 0; aspect-ratio: 3 / 4; overflow: hidden;
  position: relative;
  background: #111;
}
.about__portrait img {
  width: 100%; height: 100%; object-fit: cover;
  /* heavy monochrome treatment — full grayscale, lifted contrast, deepened blacks */
  filter: grayscale(1) contrast(1.18) brightness(.88);
}
/* four-corner vignette — radial + linear stack for even depth */
.about__portrait-vignette {
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    /* TL corner */  radial-gradient(ellipse 60% 55% at 0% 0%,     rgba(0,0,0,.65) 0%, rgba(0,0,0,0) 70%),
    /* TR corner */  radial-gradient(ellipse 60% 55% at 100% 0%,   rgba(0,0,0,.65) 0%, rgba(0,0,0,0) 70%),
    /* BL corner */  radial-gradient(ellipse 60% 55% at 0% 100%,   rgba(0,0,0,.65) 0%, rgba(0,0,0,0) 70%),
    /* BR corner */  radial-gradient(ellipse 60% 55% at 100% 100%, rgba(0,0,0,.65) 0%, rgba(0,0,0,0) 70%),
    /* overall vignette halo around edges */
    radial-gradient(ellipse 130% 130% at 50% 50%, rgba(0,0,0,0) 40%, rgba(0,0,0,.55) 100%);
  mix-blend-mode: multiply;
}
.about__copy { display: grid; gap: clamp(28px, 3vw, 44px); align-content: start; }
.about__title {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(40px, 5.8vw, 96px);
  line-height: .96; letter-spacing: -.02em;
}
.about__title em { font-style: italic; color: var(--accent); }
.about__title .line { display: block; overflow: hidden; padding-block: .04em; }
.about__title .word {
  display: inline-block; transform: translate3d(0, 110%, 0);
  transition: transform .9s var(--ease-slow);
}
.about__title.is-in .word { transform: translate3d(0, 0, 0); }
.about__title.is-in .line:nth-child(2) .word { transition-delay: .08s; }
.about__title.is-in .line:nth-child(3) .word { transition-delay: .16s; }
.about__title.is-in .line:nth-child(4) .word { transition-delay: .24s; }
.about__text {
  max-width: 56ch; color: var(--ink-70);
  font-size: clamp(15px, 1.1vw, 17px); line-height: 1.65;
}
@media (max-width: 900px) {
  .about { grid-template-columns: 1fr; }
}

/* ==============================================================
   PRACTICE (services)
   ============================================================== */
.services {
  padding: var(--pad-y) var(--pad-x);
  background: var(--paper-2);
  border-block: 1px solid var(--ink-10);
}
.services__title {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(56px, 9vw, 160px);
  line-height: .9; letter-spacing: -.02em;
  max-width: 1800px; margin: 0 auto clamp(40px, 6vw, 80px);
}
.services__title em { font-style: italic; color: var(--accent); }
.services__title .line { display: block; overflow: hidden; padding-block: .04em; }
.services__title .word {
  display: inline-block; transform: translate3d(0, 110%, 0);
  transition: transform .9s var(--ease-slow);
}
.services__title.is-in .word { transform: translate3d(0, 0, 0); }
.services__title.is-in .line:nth-child(2) .word { transition-delay: .1s; }

.services__list {
  max-width: 1800px; margin-inline: auto;
  border-top: 1px solid var(--ink-20);
}
.svc {
  display: grid; grid-template-columns: 80px 1fr;
  gap: 24px;
  padding: clamp(20px, 2.4vw, 36px) 0;
  border-bottom: 1px solid var(--ink-20);
  align-items: baseline;
  transition: padding-left .4s var(--ease);
}
.svc:hover { padding-left: 24px; }
.svc__num {
  font-size: 11px; letter-spacing: .28em; text-transform: uppercase;
  opacity: .5;
}
.svc__label {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(28px, 3.6vw, 56px);
  line-height: 1.02;
  letter-spacing: -.01em;
}

/* ==============================================================
   CONTACT
   ============================================================== */
.contact {
  padding: var(--pad-y) var(--pad-x);
  background: var(--ink);
  color: var(--paper);
  display: grid;
  gap: clamp(36px, 4vw, 60px);
  align-content: center;
  min-height: 70svh;
  max-width: none;
}
.contact__title {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(80px, 13vw, 240px);
  line-height: .9; letter-spacing: -.03em;
  margin: 0 auto; max-width: 1800px; width: 100%;
}
.contact__title em { font-style: italic; color: var(--accent); }
.contact__title .line { display: block; overflow: hidden; padding-block: .04em; }
.contact__title .word {
  display: inline-block; transform: translate3d(0, 110%, 0);
  transition: transform 1s var(--ease-slow);
}
.contact__title.is-in .word { transform: translate3d(0, 0, 0); }
.contact__title.is-in .line:nth-child(2) .word { transition-delay: .08s; }

.contact__mail {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: clamp(28px, 3.6vw, 52px);
  margin: 0 auto; max-width: 1800px; width: 100%;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255,255,255,.22);
  transition: color .4s var(--ease), border-color .4s var(--ease);
}
.contact__mail:hover { color: var(--accent); border-bottom-color: var(--accent); }
.contact__note {
  margin: 18px auto 0;
  max-width: 1800px; width: 100%;
  font-family: var(--sans);
  font-size: 12.5px;
  letter-spacing: 0.02em;
  color: rgba(255,255,255,.48);
}

/* Obfuscated email fallback (pre-JS / no-JS) — CSS unicode-bidi reversal.
   The DOM text is reversed (e.g. "moc.regneafla.yhpargotohp@olleh"),
   so naive scrapers scanning textContent get garbage. The browser
   renders it visually correct via RTL override. Modern Chromium/WebKit
   preserve visual order on copy, so user-facing UX is normal.
   JS-assembly replaces the whole innerHTML at load — this fallback
   only shows in the <5% no-JS window. */
.mail-rev {
  unicode-bidi: bidi-override;
  direction: rtl;
  /* inherits font-family, size, style from parent <a> */
}

/* ==============================================================
   FOOTER — 4-band, agency-grade
   Band 1: meta strip (dateline + live time)
   Band 2: 3-col info triplet (contact · ethos · place)
   Band 3: mega wordmark (mix-blend-mode difference)
   Band 4: colophon (copyright · impressum · back-to-top)
   ============================================================== */
.foot {
  background: var(--ink);
  color: var(--paper);
  padding: clamp(48px, 7vw, 100px) var(--pad-x) 0;
  position: relative;
  overflow: hidden;
  isolation: isolate;             /* contain blend modes within footer */
}
.foot__inner {
  max-width: 1800px; margin: 0 auto;
  display: grid;
  gap: clamp(36px, 5.5vw, 72px);
}

/* ---- Band 1 · Meta strip ---- */
.foot__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-bottom: 22px;
  border-bottom: 1px solid rgba(255,255,255,.1);
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: rgba(255,255,255,.58);
}
.foot__meta-right {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
}
.foot__live-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  margin-right: 4px;
  transform: translateY(-1px);
  animation: foot-live 2.2s ease-in-out infinite;
}
@keyframes foot-live {
  0%,100% { opacity: .4; transform: translateY(-1px) scale(1); }
  50%     { opacity: 1;  transform: translateY(-1px) scale(1.25); }
}
.foot__time {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-variant-numeric: tabular-nums;
  font-size: 15px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--paper);
}
.foot__place { margin-left: 2px; }

/* ---- Band 2 · Triplet ---- */
.foot__triplet {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(28px, 4vw, 60px);
  padding-bottom: 36px;
  border-bottom: 1px solid rgba(255,255,255,.1);
}
.foot__col { display: grid; gap: 10px; align-content: start; }
.foot__col--right { text-align: right; }
.foot__col--right > * { justify-self: end; }
.foot__col-label {
  font-family: var(--sans);
  font-size: 10px; font-weight: 500;
  letter-spacing: .32em; text-transform: uppercase;
  color: rgba(255,255,255,.42);
}
.foot__col-text {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: clamp(15px, 1.2vw, 19px);
  line-height: 1.55;
  color: rgba(255,255,255,.82);
  margin: 0;
  max-width: 30ch;
}
.foot__col--right .foot__col-text { margin-left: auto; }

/* ---- Social: monochrome icons + handle ---- */
.foot__social {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin: 2px 0 4px;
}
.foot__social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  color: var(--paper);
  opacity: .72;
  transition: opacity .35s var(--ease), transform .45s cubic-bezier(0.22, 1, 0.36, 1);
}
.foot__social-link:hover {
  opacity: 1;
  transform: translateY(-3px);
}
.foot__social-link svg { width: 100%; height: 100%; display: block; }
.foot__social-handle {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: clamp(14px, 1vw, 17px);
  color: rgba(255,255,255,.68);
  letter-spacing: 0;
  text-transform: none;
  margin-left: 4px;
  padding-top: 1px;  /* optical alignment with icons */
}
/* Values text sits below the social row — shorter max-width for rhythm */
.foot__col-text--values { max-width: 26ch; }
.foot__mail {
  font-family: var(--serif); font-style: italic;
  font-size: clamp(15px, 1.2vw, 19px);
  color: var(--paper);
  border-bottom: 1px solid rgba(255,255,255,.2);
  padding-bottom: 2px;
  width: fit-content;
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.foot__mail:hover { color: var(--accent); border-bottom-color: var(--accent); }
.foot__coord {
  font-family: var(--sans); font-style: normal;
  font-size: 11px;
  letter-spacing: .06em;
  color: rgba(255,255,255,.45);
  display: inline-block;
  margin-top: 4px;
}

/* ---- Band 3 · MEGA WORDMARK ----
   Sized so "PHOTOGRAPHY" (the longer of the 2 words at 11 chars) fits
   the content column at every viewport. wdth 78 = compressed for tight
   fit, line-height .82 so the lines sit close together, letterspacing
   negative so characters nearly touch. */
.foot__mega {
  font-family: var(--sans);
  font-weight: 500;
  font-variation-settings: "wght" var(--foot-w, 500), "wdth" 78, "opsz" 96;
  font-size: clamp(44px, 13vw, 200px);
  line-height: .82;
  letter-spacing: -.045em;
  text-transform: uppercase;
  color: #fff;
  mix-blend-mode: difference;
  padding: 0 0 .02em;
  margin: 0;
  display: grid;
  gap: 0;
  transition: font-variation-settings .3s cubic-bezier(.2,.8,.2,1);
}
.foot__mega-line {
  display: block;
  padding-block: .04em;
  line-height: .82;
}

/* ---- Band 4 · Colophon ---- */
.foot__colophon {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 24px 0 30px;
  border-top: 1px solid rgba(255,255,255,.1);
  font-family: var(--sans);
  font-size: 10.5px; font-weight: 500;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(255,255,255,.5);
}
.foot__colophon a {
  color: rgba(255,255,255,.78);
  transition: color .3s var(--ease);
}
.foot__colophon a:hover { color: var(--paper); }
.foot__sep { opacity: .4; padding: 0 10px; }

.foot__top {
  display: inline-flex;
  gap: 14px;
  align-items: baseline;
  position: relative;
  padding: 4px 2px 6px;
}
.foot__top::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform .55s cubic-bezier(0.76, 0, 0.24, 1);
}
.foot__top:hover::after { transform: scaleX(1); transform-origin: left center; }
.foot__top-arrow {
  display: inline-block;
  transition: transform .5s cubic-bezier(0.76, 0, 0.24, 1);
}
.foot__top:hover .foot__top-arrow { transform: translateY(-4px); }

/* ---- Scroll-reveal choreography ---- */
.foot__meta,
.foot__triplet,
.foot__mega,
.foot__colophon {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity   .9s cubic-bezier(0.22, 1, 0.36, 1),
    transform .9s cubic-bezier(0.22, 1, 0.36, 1);
}
.foot.is-in .foot__meta     { opacity: 1; transform: none; transition-delay: 0s;   }
.foot.is-in .foot__triplet  { opacity: 1; transform: none; transition-delay: .15s; }
.foot.is-in .foot__mega     { opacity: 1; transform: none; transition-delay: .32s; }
.foot.is-in .foot__colophon { opacity: 1; transform: none; transition-delay: .58s; }

/* ---- Mobile ---- */
@media (max-width: 780px) {
  .foot { padding-top: clamp(36px, 10vw, 60px); }
  .foot__meta {
    flex-direction: column;
    gap: 10px;
    align-items: flex-start;
    font-size: 9.5px;
    letter-spacing: .24em;
  }
  .foot__triplet {
    grid-template-columns: 1fr;
    gap: 26px;
  }
  .foot__col--right { text-align: left; }
  .foot__col--right > * { justify-self: start; }
  .foot__col--right .foot__col-text { margin-left: 0; }
  /* mega wordmark inherits base clamp — floor (44px) covers 320–480 viewports */
  .foot__colophon {
    flex-direction: column;
    gap: 16px;
    align-items: flex-start;
    padding: 22px 0 28px;
    font-size: 9.5px;
    letter-spacing: .2em;
  }
  .foot__sep { padding: 0 6px; }
}

@media (prefers-reduced-motion: reduce) {
  .foot__meta, .foot__triplet, .foot__mega, .foot__colophon {
    opacity: 1; transform: none; transition: none;
  }
  .foot__live-dot { animation: none; opacity: .8; }
}

/* ==============================================================
   CHAPTER NAVIGATION — prev / next pair at end of gallery pages
   Full-width 50/50 split, tall (85svh), full-bleed hero per half,
   italic-serif display title bottom-corner, tiny caps eyebrow +
   arrow top-corner. Four categories form a loop (Nature ↔ Urban
   ↔ Architecture ↔ Art) so Art.next wraps to Nature, Nature.prev
   wraps to Art. Single hover transform (scale + filter, no stack).
   ============================================================== */
.chap-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 100%;
  height: 85svh;
  min-height: 540px;
  background: #0a0a0a;
  color: var(--paper);
  isolation: isolate;              /* contain child blend-modes */
  overflow: hidden;
}

.chap-nav__half {
  position: relative;
  overflow: hidden;
  display: block;
  color: inherit;
  text-decoration: none;
  isolation: isolate;
  cursor: pointer;
}

.chap-nav__bg {
  position: absolute; inset: -2% -1%;
  background-image: var(--img);
  background-size: cover;
  background-position: center;
  transform: scale(1);
  /* Default = subtly desaturated + dimmed so the hover-state reads
     as a visible lift. No full grayscale (that's 2019-era). */
  filter: grayscale(.55) brightness(.58) contrast(1.02);
  will-change: transform, filter;
  transition:
    transform 1s cubic-bezier(.2,.8,.2,1),
    filter .8s cubic-bezier(.2,.8,.2,1);
}

.chap-nav__overlay {
  position: absolute; inset: 0;
  pointer-events: none;
  /* dark at top (for eyebrow contrast), lighter in middle,
     heavy at bottom (for title/meta contrast) */
  background:
    linear-gradient(180deg,
      rgba(0,0,0,.45) 0%,
      rgba(0,0,0,.15) 35%,
      rgba(0,0,0,.15) 55%,
      rgba(0,0,0,.72) 100%);
  transition: background .6s var(--ease);
}

/* Top-corner: arrow + eyebrow label side by side */
.chap-nav__arrow {
  position: absolute;
  top: clamp(26px, 3vw, 44px);
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(28px, 3.2vw, 50px);
  line-height: 1;
  color: var(--paper-68);
  pointer-events: none;
  z-index: 2;
  transition:
    transform .55s cubic-bezier(.76,0,.24,1),
    color .5s var(--ease);
}
.chap-nav__prev .chap-nav__arrow { left: clamp(26px, 3vw, 44px); }
.chap-nav__next .chap-nav__arrow { right: clamp(26px, 3vw, 44px); }

.chap-nav__eyebrow {
  position: absolute;
  top: clamp(36px, 3.5vw, 52px);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--paper-68);
  pointer-events: none;
  z-index: 2;
  transition: color .5s var(--ease);
}
.chap-nav__prev .chap-nav__eyebrow { left: clamp(72px, 6.5vw, 110px); }
.chap-nav__next .chap-nav__eyebrow { right: clamp(72px, 6.5vw, 110px); text-align: right; }

/* Bottom-corner: title + meta */
.chap-nav__body {
  position: absolute;
  bottom: clamp(36px, 4.6vw, 76px);
  display: grid;
  gap: clamp(10px, 1vw, 18px);
  z-index: 2;
  pointer-events: none;    /* anchor wraps everything — keep click clean */
  max-width: calc(100% - clamp(64px, 7vw, 100px));
}
.chap-nav__prev .chap-nav__body { left: clamp(32px, 3.6vw, 56px); text-align: left; }
.chap-nav__next .chap-nav__body { right: clamp(32px, 3.6vw, 56px); text-align: right; }

.chap-nav__title {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(64px, 9vw, 180px);
  line-height: .94;
  letter-spacing: -.015em;
  color: var(--paper-92);
  margin: 0;
}

.chap-nav__meta {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  font-variant-numeric: tabular-nums slashed-zero;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--paper-68);
  max-width: 44ch;
}
.chap-nav__next .chap-nav__meta { margin-left: auto; }

/* Hover (cursor devices only) — ONE transform lifts the half:
   image de-desaturates + scales slightly, overlay lightens, arrow
   drifts toward the viewport edge, eyebrow + colours lift. */
@media (hover: hover) and (pointer: fine) {
  .chap-nav__half:hover .chap-nav__bg,
  .chap-nav__half:focus-visible .chap-nav__bg {
    filter: grayscale(0) brightness(1) contrast(1.04);
    transform: scale(1.04);
  }
  .chap-nav__half:hover .chap-nav__overlay,
  .chap-nav__half:focus-visible .chap-nav__overlay {
    background:
      linear-gradient(180deg,
        rgba(0,0,0,.28) 0%,
        rgba(0,0,0,0)   28%,
        rgba(0,0,0,.05) 52%,
        rgba(0,0,0,.58) 100%);
  }
  .chap-nav__half:hover .chap-nav__arrow,
  .chap-nav__half:focus-visible .chap-nav__arrow {
    color: var(--paper-92);
  }
  .chap-nav__prev:hover .chap-nav__arrow,
  .chap-nav__prev:focus-visible .chap-nav__arrow {
    transform: translateX(-10px);
  }
  .chap-nav__next:hover .chap-nav__arrow,
  .chap-nav__next:focus-visible .chap-nav__arrow {
    transform: translateX(10px);
  }
  .chap-nav__half:hover .chap-nav__eyebrow,
  .chap-nav__half:focus-visible .chap-nav__eyebrow {
    color: var(--paper-92);
  }
}

/* Mobile — drop the prev half entirely. "Up next" becomes a single
   dominant cinematic panel (75svh). The 4-category loop (Nature ↔
   Urban ↔ Architecture ↔ Art) means every chapter is still reachable
   by continuing forward — prev is navigationally redundant on phone
   where vertical real-estate is scarce. Matches top-agency mobile
   pattern (Locomotive / Immersive Garden / OFF+BRAND / Resn all drop
   prev on touch).
   Hover effects inherit the (hover: hover) gate — so touch devices
   stay at the default treatment, which is why mobile sizes are
   bumped slightly: the panel has to earn its presence without an
   interactive upgrade. */
@media (max-width: 780px) {
  .chap-nav {
    grid-template-columns: 1fr;
    height: auto;
    min-height: 0;
  }
  .chap-nav__prev {
    display: none;
  }
  .chap-nav__next {
    height: 75svh;
    min-height: 480px;
  }
  .chap-nav__title {
    font-size: clamp(56px, 13vw, 100px);
  }
  .chap-nav__body {
    bottom: clamp(32px, 4.5vw, 52px);
  }
  .chap-nav__arrow {
    font-size: clamp(26px, 6.5vw, 40px);
  }
}

/* Reduced motion — no scale/filter hover transforms, keep static */
@media (prefers-reduced-motion: reduce) {
  .chap-nav__bg { transition: none; transform: none !important; }
  .chap-nav__overlay { transition: none; }
  .chap-nav__arrow { transition: color .3s ease; transform: none !important; }
}

/* ==============================================================
   SECTION INTROS (subtle top hairline only)
   ============================================================== */
[data-section] { position: relative; }
[data-section]::before {
  content: "";
  position: absolute; top: 0; left: var(--pad-x); right: var(--pad-x);
  height: 1px; background: var(--ink-10);
  transform: scaleX(0); transform-origin: left;
  transition: transform 1.2s var(--ease-slow);
}
[data-section].is-in::before { transform: scaleX(1); }
.contact::before { background: rgba(255,255,255,.14); }

/* ==============================================================
   REDUCED MOTION
   ============================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}
