:root {
  --paper: #ffffff;
  --ink: #000000;
  --quiet: #8c8c8c;
  --slot: #eeeeee;
  --hairline: #e6e6e6;
  --brand: #e05828; /* APTO orange, sampled from the logo. Logo, focus ring, link underlines only. */
  --edge: clamp(16px, 2.5vw, 40px);
  --font: "Outfit", "Avenir Next", "Century Gothic", system-ui, sans-serif;
  --bar-h: 75px; /* measured by the script; this is the fallback */
  --ease: cubic-bezier(0.22, 0.61, 0.12, 1); /* one curve for everything that moves */
  --sbw: 0px; /* scrollbar width, set while the lightbox locks the page */
  --deep: 4%; /* parallax: how far a wide plate's image may travel inside its frame, each way */
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; background: var(--paper); }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 300;
  font-size: 1rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.locked { overflow: hidden; padding-right: var(--sbw); }

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--brand); outline-offset: 5px; }
figure, h1, h2, h3, p, address, ul { margin: 0; }
ul { padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

/* Header: a plain white bar that stays put. The hero starts beneath it,
   so the colour logo and the black nav always sit on paper. */
.bar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 16px var(--edge);
  background: var(--paper);
}
.mark { display: block; line-height: 0; }
.mark img { width: 78px; height: auto; }
.bar nav { display: flex; gap: 22px; font-size: 0.8125rem; letter-spacing: 0.01em; }
.bar nav a { padding: 2px 0; border-bottom: 1px solid transparent; transition: border-color 300ms var(--ease); }
.bar nav a:hover { border-bottom-color: var(--brand); }

/* Hero: the bar photograph, edge to edge, cut short enough that the first
   line of the statement shows beneath it on a laptop screen. */
.hero {
  position: relative;
  height: min(calc(100vw * 2 / 3), 70svh, 820px);
  overflow: hidden;
  background: var(--slot);
}
.hero .shot { display: block; height: 100%; }
.hero .shot:focus-visible { outline-offset: -6px; }
.hero .shift { position: relative; height: 100%; }
.hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 55%;
}
/* Parallax on: the image layer is 28% taller than its frame, all of it
   hanging above, so it can move slower than the page and never show an edge. */
.px .hero .shift { height: 128%; top: -28%; will-change: transform; }
.px .hero img { object-position: center 5%; }

/* Statement: three lines on white, the first visible on load */
.statement {
  padding: clamp(40px, 6vh, 72px) var(--edge) clamp(96px, 14vh, 200px);
}
.statement h1 {
  font-weight: 200;
  font-size: clamp(1.875rem, 4.9vw, 4.75rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  max-width: 40ch;
}
.statement .line { display: inline-block; }

/* Work */
.wall { display: grid; gap: clamp(64px, 9vw, 160px); }

/* The section head doubles as the project switcher. It stays put beneath
   the main bar while you are inside the work, so the active name tells
   you which project you are looking at. */
.wall-head {
  position: sticky;
  top: var(--bar-h);
  z-index: 9;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  padding: 10px var(--edge) 11px;
  background: var(--paper);
  border-bottom: 1px solid var(--hairline);
  font-size: 0.8125rem;
}
.wall-head h2 { font-weight: 300; font-size: inherit; color: var(--quiet); }
.switch { display: flex; gap: 22px; }
.switch a {
  padding: 2px 0;
  color: var(--quiet);
  border-bottom: 1px solid transparent;
  white-space: nowrap;
  transition: color 300ms var(--ease), border-color 300ms var(--ease);
}
.switch a:hover { border-bottom-color: var(--brand); }
.switch a[aria-current="true"] { color: var(--ink); border-bottom-color: var(--ink); }
.switch a[aria-current="true"]:hover { border-bottom-color: var(--brand); }

.project { display: grid; gap: clamp(64px, 9vw, 160px); scroll-margin-top: calc(var(--bar-h) + 44px); }
#work, #studio, #contact { scroll-margin-top: var(--bar-h); }
.project + .project { margin-top: clamp(40px, 6vw, 100px); }
.project-head { padding: 0 var(--edge); }
.project-head h3 {
  font-weight: 200;
  font-size: clamp(1.625rem, 3.2vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.project-head .project-note {
  margin-top: 0.6em;
  max-width: 44ch;
  font-size: clamp(1rem, 1.25vw, 1.25rem);
  color: var(--quiet);
}
/* Projects still on the drawing board say so, quietly, beside the title */
.title-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 20px; }
.status { font-size: 0.8125rem; color: var(--quiet); }

/* Plates */
.plate figcaption {
  margin: 10px var(--edge) 0;
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--quiet);
  transition: color 300ms var(--ease);
}
.plate:hover figcaption { color: var(--ink); }
.shot { display: block; cursor: zoom-in; }
.frame { position: relative; width: 100%; background: var(--slot); overflow: hidden; }
.frame .depth { position: absolute; inset: 0; }
.frame img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; }
.landscape { aspect-ratio: 3 / 2; }
.portrait { aspect-ratio: 2 / 3; }
.tall { aspect-ratio: 4 / 5; } /* the two near-square frames, 1647 and 1653 by 2000 */
/* Frames for the renderings, cut to their own proportions so nothing is cropped away */
.r16x9 { aspect-ratio: 16 / 9; }
.r5x3 { aspect-ratio: 5 / 3; }
.r5x4 { aspect-ratio: 5 / 4; }
.r6x5 { aspect-ratio: 6 / 5; }
.r1x1 { aspect-ratio: 1; }
.r2x1 { aspect-ratio: 1796 / 876; }

.plate.left { width: 46%; }
.plate.right { width: 46%; margin-left: auto; }
.plate.right.wide { width: 72%; }
.plate.right figcaption { text-align: right; }
/* Renderings are lower resolution than the photographs: 60% of the page,
   and never wider than about their own pixels. */
.plate.big { width: 60%; max-width: 1180px; }

.pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(8px, 3vw, 48px);
  width: 78%;
  margin-left: auto;
}
.pair .plate:last-child figcaption { text-align: right; }

/* A render and its plan side by side, feet on the same line */
.duo { display: flex; align-items: flex-end; justify-content: space-between; }
.duo .plate.plan { width: 34%; }
.duo .plate.plan figcaption { text-align: right; }

/* The rest of a project: a strip of small frames whose widths follow their
   proportions so every frame in the row is the same height. */
.more { display: grid; gap: 18px; }
.more-toggle {
  width: fit-content;
  margin: 0 var(--edge);
  padding: 2px 0;
  font-size: 0.8125rem;
  border-bottom: 1px solid var(--ink);
  transition: border-color 300ms var(--ease);
}
.more-toggle:hover { border-bottom-color: var(--brand); }
.more-toggle .when-open { display: none; }
.more.open .more-toggle .when-open { display: inline; }
.more.open .more-toggle .when-closed { display: none; }
.more-panel { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 700ms var(--ease); }
.more.closed .more-panel { grid-template-rows: 0fr; }
.more-panel > * { min-height: 0; overflow: hidden; }
.more-grid { display: flex; gap: 8px; align-items: flex-start; }
.more-grid .plate { flex: 0.667 1 0; min-width: 0; } /* grow by aspect ratio: 2:3 frames... */
.more-grid .plate:has(.tall) { flex-grow: 0.82; }   /* ...and the 4:5 one, so the row shares one height */
.more-grid figcaption { margin: 8px 0 0; }
.more-grid .plate:first-child figcaption { margin-left: var(--edge); }
.more-grid .plate:last-child figcaption { margin-right: var(--edge); text-align: right; }

/* Parallax, in three depths. The script adds .px to <html> only on a wide,
   mouse-driven screen without a reduced-motion preference, and moves things
   with transforms alone:
   - behind the page: the hero image, and the image inside a wide plate,
     which is oversized by --deep top and bottom so it can drift within
     its frame without showing an edge
   - the page itself
   - in front of it: narrow offset plates, project titles and the statement,
     which lead the scroll by a few pixels.
   Everything is laid out exactly as it would be without the effect. */
.px .plate[data-px="deep"] .depth { inset: calc(-1 * var(--deep)) 0; }

/* Motion: photographs uncover as they arrive, then settle. One treatment,
   one curve, staggered inside a group with --i. The pre-state exists only
   when the script is running, so nothing is hidden without it. */
.js .plate .frame {
  clip-path: inset(0 0 0 0);
  transition: clip-path 900ms var(--ease) var(--d, 0ms);
}
.js .plate .frame img {
  transition: transform 1300ms var(--ease) var(--d, 0ms);
}
.js .plate.wait .frame { clip-path: inset(0 0 100% 0); }
.js .plate.wait .frame img { transform: scale(1.06); }
.js .plate { --d: calc(var(--i, 0) * 130ms); }
.js .plate.wait figcaption { opacity: 0; }
.js .plate figcaption { transition: color 300ms var(--ease), opacity 600ms var(--ease) calc(var(--d, 0ms) + 350ms); }

/* Hover, once a plate has settled: a slow lift of the image */
.js .plate.settled .frame img { transition: transform 450ms var(--ease); }
.js .plate.settled .shot:hover img,
.js .plate.settled .shot:focus-visible img { transform: scale(1.03); }

/* Page load: hero uncovers, the mark and nav follow, then the statement */
.js .hero { animation: uncover 1100ms var(--ease) both; }
.js .hero img { animation: settle 1700ms var(--ease) both; }
.js .bar .mark, .js .bar nav { animation: appear 700ms var(--ease) 450ms both; }
.js .statement .line { animation: rise 800ms var(--ease) both; }
.js .statement .line:nth-child(1) { animation-delay: 850ms; }
.js .statement .line:nth-child(2) { animation-delay: 970ms; }
.js .statement .line:nth-child(3) { animation-delay: 1090ms; }

@keyframes uncover { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes settle { from { transform: scale(1.06); } to { transform: none; } }
@keyframes appear { from { opacity: 0; } to { opacity: 1; } }
@keyframes rise { from { opacity: 0; transform: translateY(0.35em); } to { opacity: 1; transform: none; } }

/* Studio: short copy, set to the right half of the page */
.studio {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--edge);
  padding: clamp(120px, 16vw, 260px) var(--edge) 0;
}
.studio h2, .contact h2 {
  font-weight: 300;
  font-size: 0.8125rem;
  color: var(--quiet);
}
.studio-copy {
  display: grid;
  gap: 1.1em;
  font-size: clamp(1rem, 1.2vw, 1.1875rem);
  line-height: 1.5;
  max-width: 52ch;
}
.studio-copy .lead {
  font-size: clamp(1.25rem, 1.75vw, 1.75rem);
  line-height: 1.35;
  letter-spacing: -0.005em;
  margin-bottom: 0.4em;
}
.studio-copy address {
  font-style: normal;
  font-size: 0.875rem;
  color: var(--quiet);
  padding-top: 0.6em;
}

/* Tagline: one line set large on white, the last word before the contact */
.tagline { padding: clamp(120px, 16vw, 260px) var(--edge) 0; }
.tagline p {
  font-weight: 200;
  font-size: clamp(1.75rem, 4.2vw, 4rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  max-width: 26ch;
}

/* Contact: the last plate is the email address */
.contact {
  padding: clamp(80px, 10vw, 160px) var(--edge) clamp(56px, 8vw, 120px);
}
.contact h2 { margin-bottom: 14px; }
.email {
  display: block;
  width: fit-content;
  max-width: 100%;
  font-weight: 200;
  font-size: clamp(2.125rem, 8.5vw, 8.5rem);
  line-height: 1;
  letter-spacing: -0.03em;
  overflow-wrap: anywhere;
  transition: color 300ms var(--ease);
}
.email:hover { color: var(--quiet); }
.ways {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 36px;
  margin-top: clamp(28px, 4vw, 56px);
  font-size: 1rem;
}
.ways a { border-bottom: 1px solid transparent; transition: border-color 300ms var(--ease); }
.ways a:hover { border-bottom-color: var(--brand); }
.ways li:last-child { color: var(--quiet); }

.foot {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 20px var(--edge) 28px;
  border-top: 1px solid var(--hairline);
  font-size: 0.75rem;
  color: var(--quiet);
}

/* Not found: one line on paper, the same bar and foot */
.lost {
  min-height: calc(100svh - var(--bar-h) - 70px);
  display: grid;
  align-content: center;
  gap: 22px;
  padding: clamp(80px, 12vh, 160px) var(--edge);
}
.lost h1 {
  font-weight: 200;
  font-size: clamp(2.25rem, 7vw, 6.75rem);
  line-height: 1.02;
  letter-spacing: -0.025em;
  max-width: 19ch;
}
.lost a {
  width: fit-content;
  padding: 2px 0;
  font-size: 1rem;
  border-bottom: 1px solid var(--ink);
  transition: border-color 300ms var(--ease);
}
.lost a:hover { border-bottom-color: var(--brand); }

/* Lightbox: the photograph alone on paper, caption at the foot */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  background: rgba(255, 255, 255, 0.97);
  opacity: 0;
  transition: opacity 320ms var(--ease);
}
.lightbox[hidden] { display: none; }
.lightbox.on { opacity: 1; }
.lb-stage {
  display: grid;
  place-items: center;
  min-height: 0;
  height: 100%;
  padding: clamp(56px, 8vh, 80px) clamp(56px, 7vw, 104px) 12px;
}
.lb-img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  background: var(--slot);
  opacity: 0;
  transform: scale(0.985);
  transition: opacity 420ms var(--ease), transform 700ms var(--ease);
}
.lightbox.on .lb-img.ready { opacity: 1; transform: none; }
.lightbox.on .lb-img.swap { opacity: 0; transition-duration: 180ms; transform: none; }
.lb-caption {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  padding: 0 var(--edge) clamp(20px, 3vh, 32px);
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--quiet);
}
.lb-caption .lb-text { color: var(--ink); }
.lb-btn {
  position: absolute;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  color: var(--ink);
  transition: color 300ms var(--ease);
}
.lb-btn:hover { color: var(--quiet); }
.lb-btn:focus-visible { outline-offset: -4px; }
.lb-close { top: 14px; right: calc(var(--edge) - 8px); }
.lb-prev { left: calc(var(--edge) - 12px); top: 50%; transform: translateY(-50%); }
.lb-next { right: calc(var(--edge) - 12px); top: 50%; transform: translateY(-50%); }
.lightbox.solo .lb-prev, .lightbox.solo .lb-next { display: none; }

@media (max-width: 820px) {
  .studio { grid-template-columns: 1fr; gap: 20px; }
  .plate.left, .plate.right, .plate.right.wide, .plate.big { width: 100%; max-width: none; }
  .plate.right figcaption { text-align: left; }
  .pair { width: 100%; gap: 8px; }
  .duo { flex-direction: column; align-items: stretch; gap: clamp(64px, 9vw, 160px); }
  .duo .plate.plan { width: 100%; }
  .duo .plate.plan figcaption { text-align: left; }
  .more-grid { flex-wrap: wrap; }
  .more-grid .plate { flex: 1 1 30%; }
  .more-grid .plate:has(.tall) { flex-grow: 1; }
  .more-grid .plate:first-child figcaption { margin-left: 0; }
  .more-grid .plate:last-child figcaption { margin-right: 0; text-align: left; }
  .more-grid figcaption { padding: 0 var(--edge); }
}

@media (max-width: 600px) {
  /* One flowing sentence on a phone; the whole line rises together instead of three fragments */
  .js .statement .line, .statement .line { display: inline; animation: none; }
  .js .statement h1 { animation: rise 800ms var(--ease) 850ms both; }
  :root { --bar-h: 63px; }
  .mark img { width: 64px; }
  .bar { padding: 14px var(--edge); }
  .bar nav { gap: 16px; }
  /* Taller than 3:2 so the bar fills the phone; the crop keeps the stools and marble. */
  .hero { height: auto; aspect-ratio: 4 / 5; max-height: 62svh; }
  .hero img { object-position: center 50%; }
  .statement { padding: 40px var(--edge) 96px; }
  .landscape { aspect-ratio: 4 / 3; }
  /* Four names need the whole row on a phone: the section label steps aside
     (still read out to screen readers) and the row scrolls sideways if it must. */
  .wall-head h2 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .switch { gap: 18px; max-width: 100%; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .switch::-webkit-scrollbar { display: none; }
  .more-grid .plate { flex: 1 1 45%; }
  .more-grid figcaption { padding: 0; }
  .more-grid .plate:nth-child(odd) figcaption { margin-left: var(--edge); }
  .more-grid .plate:nth-child(even) figcaption { margin-right: var(--edge); text-align: right; }
  .lb-stage { padding: 64px 12px 12px; }
  .lb-prev, .lb-next { top: auto; bottom: 48px; transform: none; }
  .lb-caption { padding-bottom: 20px; padding-right: 112px; flex-direction: column; gap: 2px; }
}

/* Anyone who asks for less motion gets the settled page, with no pre-states and no parallax */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .px .hero .shift { height: 100%; top: 0; transform: none !important; }
  .px .hero img { object-position: center 55%; }
  .px .plate[data-px="deep"] .depth { inset: 0; }
  [data-px], .frame .depth { transform: none !important; }
  .js .plate.wait .frame { clip-path: none; }
  .js .plate.wait .frame img { transform: none; }
  .js .plate.wait figcaption { opacity: 1; }
  .lightbox { opacity: 1; }
  .lb-img { opacity: 1; transform: none; }
}
